1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 /****************************************************************************/
4 /* */
5 /* File: prio.c */
6 /* */
7 /* Purpose: priority management for ddd */
8 /* */
9 /* Author: Klaus Birken */
10 /* Rechenzentrum Uni Stuttgart */
11 /* Universitaet Stuttgart */
12 /* Allmandring 30 */
13 /* 70550 Stuttgart */
14 /* internet: birken@rus.uni-stuttgart.de */
15 /* */
16 /* History: 94/04/25 kb begin */
17 /* */
18 /* Remarks: */
19 /* */
20 /****************************************************************************/
21
22 /****************************************************************************/
23 /* */
24 /* include files */
25 /* system include files */
26 /* application include files */
27 /* */
28 /****************************************************************************/
29
30 /* standard C library */
31 #include <config.h>
32 #include <cstdlib>
33 #include <cstdio>
34 #include <cstring>
35
36 #include <iomanip>
37 #include <iostream>
38
39 #include <dune/common/exceptions.hh>
40 #include <dune/common/stdstreams.hh>
41
42 #include <dune/uggrid/parallel/ddd/dddi.h>
43
44 USING_UG_NAMESPACE
45
46 /* PPIF namespace: */
47 using namespace PPIF;
48
49 START_UGDIM_NAMESPACE
50
51 /****************************************************************************/
52 /* */
53 /* defines in the following order */
54 /* */
55 /* compile time constants defining static data size (i.e. arrays) */
56 /* other constants */
57 /* macros */
58 /* */
59 /****************************************************************************/
60
61
62 /* get index for one-dimensional storage of twodimensional symm. matrix,
63 which is stored as lower triangle and diagonal
64
65 col must be <= row !
66 */
67 #define PM_ENTRY(pm,row,col) (pm[((((row)+1)*(row))/2)+(col)])
68 #define PM_SIZE ((MAX_PRIO*(MAX_PRIO+1))/2)
69
70
71 /* get priority-merge value for given default mode */
72 #define PM_GETDEFAULT(mm,p1,p2,pres) \
73 switch (mm) { \
74 case PRIOMERGE_MAXIMUM : pres = MAX(p1,p2); break; \
75 case PRIOMERGE_MINIMUM : pres = MIN(p1,p2); break; \
76 default : pres = 0; break; \
77 }
78
79
80 /****************************************************************************/
81 /* */
82 /* data structures */
83 /* */
84 /****************************************************************************/
85
86
87
88 /****************************************************************************/
89 /* */
90 /* definition of static variables */
91 /* */
92 /****************************************************************************/
93
94
95
96
97
98 /****************************************************************************/
99 /* */
100 /* routines */
101 /* */
102 /****************************************************************************/
103
104
105
DDD_PrioritySet(DDD::DDDContext & context,DDD_HDR hdr,DDD_PRIO prio)106 void DDD_PrioritySet(DDD::DDDContext& context, DDD_HDR hdr, DDD_PRIO prio)
107 {
108 /* check input parameters */
109 if (prio>=MAX_PRIO)
110 DUNE_THROW(Dune::Exception, "priority must be less than " << MAX_PRIO);
111
112 # ifdef LogObjects
113 Dune::dinfo << "LOG DDD_PrioritySet " << OBJ_GID(hdr)
114 << " old=" << OBJ_PRIO(hdr) << " new=" << prio << "\n";
115 # endif
116
117 if (ddd_XferActive(context))
118 {
119 /* we are during Xfer, therefore initiate PrioChange operation */
120 DDD_XferPrioChange(context, hdr, prio);
121 }
122 else if(ddd_PrioActive(context))
123 {
124 /* we are in a Prio-environment, therefore initiate consistent PrioChange operation */
125 DDD_PrioChange(context, hdr, prio);
126 }
127 else
128 {
129 if (! ObjHasCpl(context, hdr))
130 {
131 /* just one local object, we can simply change its priority */
132 OBJ_PRIO(hdr) = prio;
133 }
134 else
135 {
136 /* distributed object will get inconsistent here. issue warning. */
137 if (DDD_GetOption(context, OPT_WARNING_PRIOCHANGE)==OPT_ON)
138 Dune::dwarn << "DDD_PrioritySet: creating inconsistency for gid="
139 << OBJ_GID(hdr) << "\n";
140
141 /* change priority, nevertheless */
142 OBJ_PRIO(hdr) = prio;
143 }
144 }
145 }
146
147
148
149
150
151 /****************************************************************************/
152
153 /*
154 compute the result of merging two priorities.
155
156 this function merges two priorities p1 and p2 for
157 object of DDD_TYPE desc. the default merge operation
158 is used (PRIOMERGE_DEFAULT). if a merge-matrix has been
159 specified, this matrix will be used.
160
161 on return, *pres will contain the resulting priority.
162 the return value is:
163
164 PRIO_UNKNOWN can't decide which priority wins.
165 PRIO_FIRST first priority wins.
166 PRIO_SECOND second priority wins.
167 PRIO_ERROR an error has occurred.
168 */
169
PriorityMerge(const TYPE_DESC * desc,DDD_PRIO p1,DDD_PRIO p2,DDD_PRIO * pres)170 enum PrioMergeVals PriorityMerge(const TYPE_DESC* desc, DDD_PRIO p1, DDD_PRIO p2, DDD_PRIO *pres)
171 {
172 /* check if matrix is available */
173 if (desc->prioMatrix == nullptr)
174 {
175 PM_GETDEFAULT(desc->prioDefault, p1, p2, *pres);
176 if (*pres==MAX_PRIO) return PRIO_ERROR;
177 }
178 else
179 {
180 if (p2<=p1)
181 {
182 *pres = PM_ENTRY(desc->prioMatrix,p1,p2);
183 }
184 else
185 {
186 *pres = PM_ENTRY(desc->prioMatrix,p2,p1);
187 }
188
189 }
190
191 if (*pres==p1 || *pres!=p2) return(PRIO_FIRST);
192 if (*pres==p2 || *pres!=p1) return(PRIO_SECOND);
193 return(PRIO_UNKNOWN);
194 }
195
196
197 /****************************************************************************/
198
199 /*
200 allocate prioMatrix and set default entries
201 */
202
SetPrioMatrix(TYPE_DESC * desc,int priomerge_mode)203 static int SetPrioMatrix (TYPE_DESC *desc, int priomerge_mode)
204 {
205 int r, c;
206
207 if (desc->prioMatrix==nullptr)
208 {
209 /* prioMatrix has not been allocated before */
210 desc->prioMatrix = std::make_unique<DDD_PRIO[]>(PM_SIZE);
211 }
212
213 for(r=0; r<MAX_PRIO; r++)
214 {
215 for(c=0; c<=r; c++)
216 {
217 DDD_PRIO pres;
218
219 PM_GETDEFAULT(priomerge_mode, r, c, pres);
220 if (pres==MAX_PRIO) return false;
221
222 PM_ENTRY(desc->prioMatrix, r, c) = pres;
223 }
224 }
225
226 /* remember default setting */
227 desc->prioDefault = priomerge_mode;
228
229 return true;
230 }
231
232
233 /****************************************************************************/
234
235 /*
236 check prioMatrix
237 */
238
CheckPrioMatrix(TYPE_DESC * desc)239 static int CheckPrioMatrix (TYPE_DESC *desc)
240 {
241 int r, c;
242
243 if (desc->prioMatrix==nullptr)
244 /* no prioMatrix defined, ok */
245 return true;
246
247 /* check: entries i must be 0<=i<MAX_PRIO */
248 for(r=0; r<MAX_PRIO; r++)
249 {
250 for(c=0; c<=r; c++)
251 {
252 DDD_PRIO p = PM_ENTRY(desc->prioMatrix,r,c);
253
254 if (p>=MAX_PRIO)
255 DUNE_THROW(Dune::Exception,
256 "PriorityMerge(" << r << "," << c << ") yields"
257 << p << " larger than " << (MAX_PRIO-1));
258 }
259 }
260
261
262 /* TODO: check for associativity */
263
264
265 return true;
266 }
267
268
269
270 /****************************************************************************/
271
272
DDD_PrioMergeDefault(DDD::DDDContext & context,DDD_TYPE type_id,int priomerge_mode)273 void DDD_PrioMergeDefault (DDD::DDDContext& context, DDD_TYPE type_id, int priomerge_mode)
274 {
275 if (! SetPrioMatrix(&context.typeDefs()[type_id], priomerge_mode))
276 DUNE_THROW(Dune::Exception, "unknown defaultprio-mergemode in DDD_TYPE " << type_id);
277 }
278
279
280
DDD_PrioMergeDefine(DDD::DDDContext & context,DDD_TYPE type_id,DDD_PRIO p1,DDD_PRIO p2,DDD_PRIO pres)281 void DDD_PrioMergeDefine (DDD::DDDContext& context, DDD_TYPE type_id,
282 DDD_PRIO p1, DDD_PRIO p2, DDD_PRIO pres)
283 {
284 TYPE_DESC *desc = &context.typeDefs()[type_id];
285
286 /* check for correct type */
287 if (! ddd_TypeDefined(desc))
288 DUNE_THROW(Dune::Exception, "undefined DDD_TYPE");
289
290
291 /* create prioMatrix on demand */
292 if (desc->prioMatrix == nullptr)
293 {
294 if (! SetPrioMatrix(desc, PRIOMERGE_DEFAULT))
295 DUNE_THROW(Dune::Exception, "error for DDD_TYPE " << type_id);
296 }
297
298
299 /* check input priorities */
300
301 if (p1>=MAX_PRIO)
302 DUNE_THROW(Dune::Exception, "invalid priority p1=" << p1);
303 if (p2>=MAX_PRIO)
304 DUNE_THROW(Dune::Exception, "invalid priority p2=" << p2);
305 if (pres>=MAX_PRIO)
306 DUNE_THROW(Dune::Exception, "invalid priority pres=" << pres);
307
308
309 /* set prioMatrix entry */
310 if (p2<=p1)
311 {
312 PM_ENTRY(desc->prioMatrix,p1,p2) = pres;
313 }
314 else
315 {
316 PM_ENTRY(desc->prioMatrix,p2,p1) = pres;
317 }
318
319
320 /* finally always check prioMatrix, just to be sure */
321 if (!CheckPrioMatrix(desc))
322 DUNE_THROW(Dune::Exception,
323 "error(s) in merge-check for DDD_TYPE " << type_id);
324 }
325
326
327 /****************************************************************************/
328
329
330 /*
331 call merge operation from application program
332 */
DDD_PrioMerge(DDD::DDDContext & context,DDD_TYPE type_id,DDD_PRIO p1,DDD_PRIO p2)333 DDD_PRIO DDD_PrioMerge (DDD::DDDContext& context, DDD_TYPE type_id, DDD_PRIO p1, DDD_PRIO p2)
334 {
335 TYPE_DESC *desc = &context.typeDefs()[type_id];
336 DDD_PRIO newprio;
337
338 /* check for correct type */
339 if (! ddd_TypeDefined(desc))
340 DUNE_THROW(Dune::Exception, "undefined DDD_TYPE");
341
342 if (p1>=MAX_PRIO)
343 DUNE_THROW(Dune::Exception, "invalid priority p1=" << p1);
344 if (p2>=MAX_PRIO)
345 DUNE_THROW(Dune::Exception, "invalid priority p2=" << p2);
346
347 if (PriorityMerge(desc, p1, p2, &newprio) == PRIO_ERROR)
348 DUNE_THROW(Dune::Exception, "cannot merge priorities");
349
350 return newprio;
351 }
352
353
354 /****************************************************************************/
355
prioMergeDefaultName(int prioDefault)356 static const char* prioMergeDefaultName(int prioDefault)
357 {
358 switch (prioDefault) {
359 case PRIOMERGE_MAXIMUM:
360 return "MAX";
361 case PRIOMERGE_MINIMUM:
362 return "MIN";
363 default:
364 return "(ERROR)";
365 }
366 }
367
DDD_PrioMergeDisplay(DDD::DDDContext & context,DDD_TYPE type_id)368 void DDD_PrioMergeDisplay (DDD::DDDContext& context, DDD_TYPE type_id)
369 {
370 std::ostream& out = std::cout;
371 TYPE_DESC* desc = &context.typeDefs()[type_id];
372 int r, c, changed_rows[MAX_PRIO];
373
374 if (context.me() != 0)
375 return;
376
377 /* check for correct type */
378 if (! ddd_TypeDefined(desc))
379 DUNE_THROW(Dune::Exception, "undefined DDD_TYPE");
380
381 out << "/ PrioMergeDisplay for '" << desc->name << "', default mode "
382 << prioMergeDefaultName(desc->prioDefault) << "\n";
383
384 if (desc->prioMatrix == nullptr)
385 {
386 out << "\\ \t(no special cases defined)\n";
387 return;
388 }
389
390 /* find out which rows/columns we will have to print */
391 for(r=0; r<MAX_PRIO; r++)
392 {
393 changed_rows[r] = false;
394
395 for(c=0; c<MAX_PRIO; c++)
396 {
397 DDD_PRIO p_dflt, p_actual;
398
399 PM_GETDEFAULT(desc->prioDefault, r, c, p_dflt);
400 PriorityMerge(desc, r, c, &p_actual);
401
402 if (p_dflt != p_actual)
403 changed_rows[r] = true;
404 }
405 }
406
407 /* print */
408 using std::setw;
409 out << "|\t ";
410 for(c=0; c<MAX_PRIO; c++)
411 {
412 if (! changed_rows[c])
413 continue;
414
415 out << " " << setw(3) << c << " ";
416 }
417 out << "\n";
418
419 for(r=0; r<MAX_PRIO; r++)
420 {
421 if (! changed_rows[r])
422 continue;
423
424 out << "|\t" << setw(2) << r << " : ";
425 for(c=0; c<MAX_PRIO; c++)
426 {
427 DDD_PRIO p_dflt, p_actual;
428
429 if (! changed_rows[c])
430 continue;
431
432 PM_GETDEFAULT(desc->prioDefault, r, c, p_dflt);
433 PriorityMerge(desc, r, c, &p_actual);
434
435 if (p_dflt != p_actual)
436 out << " " << setw(3) << p_actual << " ";
437 else
438 out << "(" << setw(3) << p_actual << ") ";
439 }
440
441 out << "\n";
442 }
443
444 out << "\\\n";
445 }
446
447 /****************************************************************************/
448
449 END_UGDIM_NAMESPACE
450