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:	  priority.c													*/
6 /*																			*/
7 /* Purpose:   functions for managing priorities of distributed objects      */
8 /*																			*/
9 /* Author:	  Stefan Lang                                                                       */
10 /*			  Institut fuer Computeranwendungen III                                                 */
11 /*			  Universitaet Stuttgart										*/
12 /*			  Pfaffenwaldring 27											*/
13 /*			  70550 Stuttgart												*/
14 /*			  email: birken@ica3.uni-stuttgart.de							*/
15 /*																			*/
16 /* History:   980201 sl  begin                                                                                          */
17 /*																			*/
18 /* Remarks:                                                                                                                             */
19 /*																			*/
20 /****************************************************************************/
21 
22 #ifdef ModelP
23 
24 /****************************************************************************/
25 /*																			*/
26 /* include files															*/
27 /*			  system include files											*/
28 /*			  application include files                                                                     */
29 /*																			*/
30 /****************************************************************************/
31 
32 #include <config.h>
33 #include <cstdlib>
34 
35 #include "parallel.h"
36 #include <dune/uggrid/ugdevices.h>
37 #include <dune/uggrid/gm/evm.h>
38 #include <dune/uggrid/gm/gm.h>
39 #include <dune/uggrid/gm/refine.h>
40 #include <dune/uggrid/gm/shapes.h>
41 #include <dune/uggrid/gm/ugm.h>
42 #include <dune/uggrid/low/debug.h>
43 #include <dune/uggrid/low/namespace.h>
44 
45 /* UG namespaces: */
46 USING_UG_NAMESPACES
47 
48 /* PPIF namespace: */
49 using namespace PPIF;
50 
51 
52 /****************************************************************************/
53 /*																			*/
54 /* defines in the following order											*/
55 /*																			*/
56 /*		  compile time constants defining static data size (i.e. arrays)	*/
57 /*		  other constants													*/
58 /*		  macros															*/
59 /*																			*/
60 /****************************************************************************/
61 
62 /* macros for merge new priority with objects existing one */
63 /* valid only for all types of ghost priorities            */
64 #define PRIO_CALC(e) ((USED(e) && THEFLAG(e)) ? PrioVHGhost :                \
65                       (THEFLAG(e)) ? PrioVGhost : (USED(e)) ?              \
66                       PrioHGhost : (assert(0),0))
67 
68 #define SETPRIOPV SETPRIOX
69 
70 /* macros for setting object priorities with related objects */
NODE_PRIORITY_SET(DDD::DDDContext & context,GRID * grid,NODE * node,INT prio)71 inline void NODE_PRIORITY_SET(DDD::DDDContext& context, GRID* grid, NODE* node, INT prio)
72 {
73   /* set priorities of node */
74   SETPRIOX(context, node, prio);
75 
76   if (VEC_DEF_IN_OBJ_OF_GRID(grid, NODEVEC) and NVECTOR(node) != nullptr)
77     SETPRIOPV(context, NVECTOR(node),prio);
78 }
79 
PRIO_SET_EDGE(DDD::DDDContext & context,EDGE * edge,INT prio)80 inline void PRIO_SET_EDGE(DDD::DDDContext& context, EDGE* edge, INT prio)
81 {
82   SETPRIOX(context, edge, prio);
83 }
84 
EDGE_PRIORITY_SET(DDD::DDDContext & context,GRID * grid,EDGE * edge,INT prio)85 inline void EDGE_PRIORITY_SET(DDD::DDDContext& context, GRID* grid, EDGE* edge, INT prio)
86 {
87   /* set priorities of node for 3D */
88   PRIO_SET_EDGE(context, edge, prio);
89 
90   /* set priority of edge vector */
91   if (VEC_DEF_IN_OBJ_OF_GRID(grid, EDGEVEC) and EDVECTOR(edge) != nullptr)
92     SETPRIOX(context, EDVECTOR(edge),prio);
93 }
94 
95 
96 /****************************************************************************/
97 /*																			*/
98 /* data structures used in this source file (exported data structures are	*/
99 /*		  in the corresponding include file!)								*/
100 /*																			*/
101 /****************************************************************************/
102 
103 
104 /****************************************************************************/
105 /*																			*/
106 /* definition of exported global variables									*/
107 /*																			*/
108 /****************************************************************************/
109 
110 
111 /****************************************************************************/
112 /*																			*/
113 /* forward declarations of functions used before they are defined			*/
114 /*																			*/
115 /****************************************************************************/
116 
117 
118 /*
119         for all PrioMaster-nodes with remote copies, set exactly one
120         to PrioMaster, the other copies to PrioBorder in order to establish
121         the BorderNodeIF. this is done for one grid.
122  */
123 
124 
125 /****************************************************************************/
126 /*
127    ComputeNodeBorderPrios -
128 
129    SYNOPSIS:
130    static int ComputeNodeBorderPrios (DDD_OBJ obj);
131 
132    PARAMETERS:
133    .  obj -
134 
135    DESCRIPTION:
136 
137    RETURN VALUE:
138    int
139  */
140 /****************************************************************************/
141 
ComputeNodeBorderPrios(DDD::DDDContext & context,DDD_OBJ obj)142 static int ComputeNodeBorderPrios (DDD::DDDContext& context, DDD_OBJ obj)
143 {
144   NODE    *node  = (NODE *)obj;
145   int     *plist = DDD_InfoProcList(context, PARHDR(node));
146   int i, min_proc = context.procs();
147 
148   /*
149           minimum processor number will get Master-node,
150           all others get Border-nodes
151    */
152   for(i=0; plist[i]>=0; i+=2)
153   {
154     if (plist[i+1]==PrioMaster && plist[i]<min_proc)
155       min_proc = plist[i];
156   }
157 
158   if (min_proc == context.procs())
159     return(0);
160 
161   if (context.me() != min_proc)
162     SETPRIO(context, node, PrioBorder);
163   return 0;
164 }
165 
166 
167 /****************************************************************************/
168 /*
169    ComputeVectorBorderPrios -
170 
171    SYNOPSIS:
172    static int ComputeVectorBorderPrios (DDD_OBJ obj);
173 
174    PARAMETERS:
175    .  obj -
176 
177    DESCRIPTION:
178 
179    RETURN VALUE:
180    int
181  */
182 /****************************************************************************/
183 
ComputeVectorBorderPrios(DDD::DDDContext & context,DDD_OBJ obj)184 static int ComputeVectorBorderPrios (DDD::DDDContext& context, DDD_OBJ obj)
185 {
186   VECTOR  *vector  = (VECTOR *)obj;
187   int     *plist = DDD_InfoProcList(context, PARHDR(vector));
188   int i, min_proc = context.procs();
189 
190   /*
191           minimum processor number will get Master-node,
192           all others get Border-nodes
193    */
194   for(i=0; plist[i]>=0; i+=2)
195   {
196     if (plist[i+1]==PrioMaster && plist[i]<min_proc)
197       min_proc = plist[i];
198   }
199 
200   if (min_proc == context.procs())
201     return(0);
202 
203   if (context.me() != min_proc)
204     SETPRIO(context, vector, PrioBorder);
205   return 0;
206 }
207 
208 
209 
210 /****************************************************************************/
211 /*
212    ComputeEdgeBorderPrios -
213 
214    SYNOPSIS:
215    static int ComputeEdgeBorderPrios (DDD_OBJ obj);
216 
217    PARAMETERS:
218    .  obj -
219 
220    DESCRIPTION:
221 
222    RETURN VALUE:
223    void
224  */
225 /****************************************************************************/
226 
ComputeEdgeBorderPrios(DDD::DDDContext & context,DDD_OBJ obj)227 static int ComputeEdgeBorderPrios (DDD::DDDContext& context, DDD_OBJ obj)
228 {
229   EDGE    *edge  =        (EDGE *)obj;
230   int             *plist =        DDD_InfoProcList(context, PARHDR(edge));
231   int i, min_proc     = context.procs();
232 
233   /*
234           minimum processor number will get Master-node,
235           all others get Border-nodes
236    */
237   for(i=0; plist[i]>=0; i+=2)
238   {
239     if (plist[i+1]==PrioMaster && plist[i]<min_proc)
240       min_proc = plist[i];
241   }
242 
243   if (min_proc == context.procs())
244     return(0);
245 
246   if (context.me() != min_proc)
247     SETPRIO(context, edge, PrioBorder);
248   return 0;
249 }
250 
251 
252 /****************************************************************************/
253 /*
254    SetGhostObjectPriorities -
255 
256    SYNOPSIS:
257    void SetGhostObjectPriorities (GRID *theGrid);
258 
259    PARAMETERS:
260    .  theGrid
261 
262    DESCRIPTION:
263 
264    RETURN VALUE:
265    void
266  */
267 /****************************************************************************/
268 
SetGhostObjectPriorities(GRID * theGrid)269 void NS_DIM_PREFIX SetGhostObjectPriorities (GRID *theGrid)
270 {
271   ELEMENT *theElement,*theNeighbor,*SonList[MAX_SONS];
272   NODE    *theNode;
273   EDGE    *theEdge;
274   VECTOR  *theVector;
275   INT i,prio,hghost,vghost;
276 
277   auto& context = theGrid->dddContext();
278   const auto& me = context.me();
279 
280   /* reset USED flag for objects of ghostelements */
281   for (theElement=PFIRSTELEMENT(theGrid);
282        theElement!=NULL;
283        theElement=SUCCE(theElement))
284   {
285     SETUSED(theElement,0); SETTHEFLAG(theElement,0);
286     for (i=0; i<EDGES_OF_ELEM(theElement); i++)
287     {
288       theEdge = GetEdge(CORNER(theElement,CORNER_OF_EDGE(theElement,i,0)),
289                         CORNER(theElement,CORNER_OF_EDGE(theElement,i,1)));
290       ASSERT(theEdge != NULL);
291       SETUSED(theEdge,0); SETTHEFLAG(theEdge,0);
292     }
293     if (VEC_DEF_IN_OBJ_OF_GRID(theGrid,SIDEVEC))
294       for (i=0; i<SIDES_OF_ELEM(theElement); i++)
295       {
296         theVector = SVECTOR(theElement,i);
297         if (theVector != NULL) {
298           SETUSED(theVector,0);
299           SETTHEFLAG(theVector,0);
300         }
301       }
302   }
303   /* to reset also nodes which are at corners of the boundary */
304   /* reset of nodes need to be done through the node list     */
305   for (theNode=PFIRSTNODE(theGrid); theNode!=NULL; theNode=SUCCN(theNode))
306   {
307     SETUSED(theNode,0); SETTHEFLAG(theNode,0);
308     SETMODIFIED(theNode,0);
309   }
310 
311   /* set FLAG for objects of horizontal and vertical overlap */
312   for (theElement=PFIRSTELEMENT(theGrid);
313        theElement!=NULL;
314        theElement=SUCCE(theElement))
315   {
316     if (PARTITION(theElement) == me) continue;
317 
318     /* check for horizontal ghost */
319     hghost = 0;
320     for (i=0; i<SIDES_OF_ELEM(theElement); i++)
321     {
322       theNeighbor = NBELEM(theElement,i);
323       if (theNeighbor == NULL) continue;
324 
325       if (PARTITION(theNeighbor) == me)
326       {
327         hghost = 1;
328         break;
329       }
330     }
331 
332     /* check for vertical ghost */
333     vghost = 0;
334     GetAllSons(theElement,SonList);
335     for (i=0; SonList[i]!=NULL; i++)
336     {
337       if (PARTITION(SonList[i]) == me)
338       {
339         vghost = 1;
340         break;
341       }
342     }
343 
344     /* one or both of vghost and hghost should be true here   */
345     /* except for elements which will be disposed during Xfer */
346 
347     if (vghost) SETTHEFLAG(theElement,1);
348     if (hghost) SETUSED(theElement,1);
349     for (i=0; i<CORNERS_OF_ELEM(theElement); i++)
350     {
351       theNode = CORNER(theElement,i);
352       if (vghost) SETTHEFLAG(theNode,1);
353       if (hghost) SETUSED(theNode,1);
354     }
355     for (i=0; i<EDGES_OF_ELEM(theElement); i++)
356     {
357       theEdge = GetEdge(CORNER_OF_EDGE_PTR(theElement,i,0),
358                         CORNER_OF_EDGE_PTR(theElement,i,1));
359       ASSERT(theEdge != NULL);
360       if (vghost) SETTHEFLAG(theEdge,1);
361       if (hghost) SETUSED(theEdge,1);
362     }
363     if (VEC_DEF_IN_OBJ_OF_GRID(theGrid,SIDEVEC))
364       for (i=0; i<SIDES_OF_ELEM(theElement); i++)
365       {
366         theVector = SVECTOR(theElement,i);
367         if (theVector != NULL) {
368           if (vghost) SETTHEFLAG(theVector,1);
369           if (hghost) SETUSED(theVector,1);
370         }
371       }
372   }
373 
374   /* set USED flag for objects of master elements */
375   /* reset FLAG for objects of master elements  */
376   for (theElement=PFIRSTELEMENT(theGrid);
377        theElement!=NULL;
378        theElement=SUCCE(theElement))
379   {
380     if (PARTITION(theElement) != me) continue;
381 
382     SETUSED(theElement,0); SETTHEFLAG(theElement,0);
383     for (i=0; i<CORNERS_OF_ELEM(theElement); i++)
384     {
385       theNode = CORNER(theElement,i);
386       SETUSED(theNode,0); SETTHEFLAG(theNode,0);
387       SETMODIFIED(theNode,1);
388     }
389     for (i=0; i<EDGES_OF_ELEM(theElement); i++)
390     {
391       theEdge = GetEdge(CORNER_OF_EDGE_PTR(theElement,i,0),
392                         CORNER_OF_EDGE_PTR(theElement,i,1));
393       ASSERT(theEdge != NULL);
394       SETUSED(theEdge,0); SETTHEFLAG(theEdge,0);
395     }
396     if (VEC_DEF_IN_OBJ_OF_GRID(theGrid,SIDEVEC))
397       for (i=0; i<SIDES_OF_ELEM(theElement); i++)
398       {
399         theVector = SVECTOR(theElement,i);
400         if (theVector != NULL) {
401           SETUSED(theVector,0);
402           SETTHEFLAG(theVector,0);
403         }
404       }
405   }
406 
407   /* set object priorities for ghostelements */
408   for (theElement=PFIRSTELEMENT(theGrid);
409        theElement!=NULL;
410        theElement=SUCCE(theElement))
411   {
412     if (PARTITION(theElement) == me) continue;
413 
414     if (USED(theElement) || THEFLAG(theElement))
415     {
416       prio = PRIO_CALC(theElement);
417       PRINTDEBUG(gm,1,("SetGhostObjectPriorities(): e=" EID_FMTX " new prio=%d\n",
418                        EID_PRTX(theElement),prio))
419       SETEPRIOX(context, theElement, prio);
420 
421       if (VEC_DEF_IN_OBJ_OF_GRID(theGrid,ELEMVEC))
422       {
423         theVector = EVECTOR(theElement);
424         if (theVector != NULL)
425           SETPRIOX(context, theVector,prio);
426       }
427     }
428 
429     /* set edge priorities */
430     for (i=0; i<EDGES_OF_ELEM(theElement); i++)
431     {
432 
433       theEdge = GetEdge(CORNER(theElement,CORNER_OF_EDGE(theElement,i,0)),
434                         CORNER(theElement,CORNER_OF_EDGE(theElement,i,1)));
435       ASSERT(theEdge != NULL);
436 
437       if (USED(theEdge) || THEFLAG(theEdge))
438       {
439         PRINTDEBUG(dddif,3,(PFMT " dddif_SetGhostObjectPriorities():"
440                             " downgrade edge=" EDID_FMTX " from=%d to PrioHGhost\n",
441                             me,EDID_PRTX(theEdge),prio));
442 
443         EDGE_PRIORITY_SET(context, theGrid,theEdge,PRIO_CALC(theEdge));
444       }
445       else
446         EDGE_PRIORITY_SET(context, theGrid,theEdge,PrioMaster);
447     }
448 
449                         #ifdef __THREEDIM__
450     /* if one(all) of the side nodes is (are) a hghost (vghost) node   */
451     /* then its a hghost (vghost) side vector                          */
452     if (VEC_DEF_IN_OBJ_OF_GRID(theGrid,SIDEVEC))
453       for (i=0; i<SIDES_OF_ELEM(theElement); i++)
454       {
455         if (USED(theVector) || THEFLAG(theVector))
456           SETPRIOX(context, theVector,PRIO_CALC(theVector));
457       }
458                         #endif
459 
460   }
461   /* to set also nodes which are at corners of the boundary   */
462   /* set them through the node list                           */
463   for (theNode=PFIRSTNODE(theGrid); theNode!=NULL; theNode=SUCCN(theNode))
464   {
465     /* check if its a master node */
466     if (USED(theNode) || THEFLAG(theNode))
467     {
468       PRINTDEBUG(dddif,3,(PFMT " dddif_SetGhostObjectPriorities():"
469                           " downgrade node=" ID_FMTX " from=%d to PrioHGhost\n",
470                           me,ID_PRTX(theNode),prio));
471 
472       /* set node priorities of node to ghost */
473       NODE_PRIORITY_SET(context, theGrid,theNode,PRIO_CALC(theNode));
474     }
475     else if (MODIFIED(theNode) == 0)
476     {
477       /* this is a node of the boundary without connection to master elements */
478       NODE_PRIORITY_SET(context, theGrid,theNode,PrioHGhost);
479     }
480     /* this is needed only for consistency after refinement */
481     /* ghost nodes which belong after refinement to master  */
482     /* elements have to be upgraded explicitly (980126 s.l.)*/
483     else if (MODIFIED(theNode) == 1)
484     {
485       NODE_PRIORITY_SET(context, theGrid,theNode,PrioMaster);
486     }
487   }
488 }
489 
490 
491 /****************************************************************************/
492 /*
493    SetBorderPriorities -
494 
495    SYNOPSIS:
496    INT SetBorderPriorities (GRID *theGrid);
497 
498    PARAMETERS:
499    .  theGrid
500 
501    DESCRIPTION:
502 
503    RETURN VALUE:
504    INT
505  */
506 /****************************************************************************/
507 
SetBorderPriorities(GRID * theGrid)508 INT NS_DIM_PREFIX SetBorderPriorities (GRID *theGrid)
509 {
510   auto& context = theGrid->dddContext();
511   const auto& dddctrl = ddd_ctrl(context);
512 
513   DDD_IFAExecLocal(context,
514                    dddctrl.BorderNodeSymmIF,GRID_ATTR(theGrid),
515                    ComputeNodeBorderPrios);
516 
517   /* TODO: distinguish two cases:
518      1. only nodevectors then setting of vector prios can
519           be done in ComputeNodeBorderPrios without extra communiction
520      2. with other vectortypes (side and/or edgevectors) use
521           ComputeVectorBorderPrios
522    */
523   DDD_IFAExecLocal(context,
524                    dddctrl.BorderVectorSymmIF,GRID_ATTR(theGrid),
525                    ComputeVectorBorderPrios);
526 
527   DDD_IFAExecLocal(context,
528                    dddctrl.BorderEdgeSymmIF,GRID_ATTR(theGrid),
529                    ComputeEdgeBorderPrios);
530 
531   return(GM_OK);
532 }
533 
534 
535 /****************************************************************************/
536 /*
537    SetGridBorderPriorities -
538 
539    SYNOPSIS:
540    INT SetGridBorderPriorities (GRID *theGrid);
541 
542    PARAMETERS:
543    .  theGrid
544 
545    DESCRIPTION:
546 
547    RETURN VALUE:
548    INT
549  */
550 /****************************************************************************/
551 
552 
SetGridBorderPriorities(GRID * theGrid)553 INT NS_DIM_PREFIX SetGridBorderPriorities (GRID *theGrid)
554 {
555   /* set border priorities on next higher level */
556   if (SetBorderPriorities(UPGRID(theGrid)) != GM_OK) return(GM_FATAL);
557 
558   return(GM_OK);
559 }
560 
561 #endif
562