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:	  gridcons.c													*/
6 /*																			*/
7 /* Purpose:   functions for managing consistency of distributed grids       */
8 /*																			*/
9 /* Author:	  Stefan Lang, Klaus Birken										*/
10 /*			  Institut fuer Computeranwendungen III                                                 */
11 /*			  Universitaet Stuttgart										*/
12 /*			  Pfaffenwaldring 27											*/
13 /*			  70550 Stuttgart												*/
14 /*																			*/
15 /* History:   960906 kb  begin                                                                                          */
16 /*																			*/
17 /* Remarks:                                                                                                                             */
18 /*																			*/
19 /****************************************************************************/
20 
21 #ifdef ModelP
22 
23 /****************************************************************************/
24 /*																			*/
25 /* include files															*/
26 /*			  system include files											*/
27 /*			  application include files                                                                     */
28 /*																			*/
29 /****************************************************************************/
30 
31 #include <config.h>
32 #include <cstdlib>
33 
34 #include "parallel.h"
35 #include <dune/uggrid/low/debug.h>
36 #include <dune/uggrid/low/namespace.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/ugdevices.h>
43 
44 /* UG namespaces: */
45 USING_UG_NAMESPACES
46 #ifdef Debug
47 using namespace PPIF;
48 #endif
49 
50 /****************************************************************************/
51 /*																			*/
52 /* defines in the following order											*/
53 /*																			*/
54 /*		  compile time constants defining static data size (i.e. arrays)	*/
55 /*		  other constants													*/
56 /*		  macros															*/
57 /*																			*/
58 /****************************************************************************/
59 
60 #ifdef DDD_PRIO_ENV
61 #define DDD_XferBegin   DDD_PrioBegin
62 #define DDD_XferEnd             DDD_PrioEnd
63 #endif
64 
65 
66 /****************************************************************************/
67 /*																			*/
68 /* data structures used in this source file (exported data structures are	*/
69 /*		  in the corresponding include file!)								*/
70 /*																			*/
71 /****************************************************************************/
72 
73 
74 /****************************************************************************/
75 /*																			*/
76 /* definition of exported global variables									*/
77 /*																			*/
78 /****************************************************************************/
79 
80 
81 /****************************************************************************/
82 /*																			*/
83 /* forward declarations of functions used before they are defined			*/
84 /*																			*/
85 /****************************************************************************/
86 
87 
88 /****************************************************************************/
89 /*
90    ConstructConsistentGridLevel -
91 
92    SYNOPSIS:
93    void ConstructConsistentGridLevel (GRID *theGrid);
94 
95    PARAMETERS:
96    .  theGrid
97 
98    DESCRIPTION:
99    Provide a consistent grid level. Do not call for a single grid level, but
100    always for the whole multigrid from bottom to top, since otherwise
101    consistency is not ensured!
102 
103    RETURN VALUE:
104    void
105  */
106 /****************************************************************************/
107 
ConstructConsistentGridLevel(GRID * theGrid)108 static void ConstructConsistentGridLevel (GRID *theGrid)
109 {
110   INT j;
111   EDGE    *theEdge;
112 
113   /* this is the simplest fix for VFATHER zombies  */
114   /* just reset all VFATHER pointers and set them  */
115   /* only by master nodes of this or upper levels. */
116   /* A more complicated fix would be to set the    */
117   /* priorities of the vertices correctly.         */
118   /* (980126 s.l.)                                 */
119   for (VERTEX* theVertex = PFIRSTVERTEX(theGrid); theVertex != NULL;
120        theVertex = SUCCV(theVertex)) {
121     VFATHER(theVertex) = NULL;
122     /*
123                 if (VXGHOST(theVertex))
124                         VFATHER(theVertex) = NULL;
125                     else if (OBJT(theVertex) == BVOBJ)
126                         if (MOVED(theVertex))
127                             {
128                                 INT n;
129                                     DOUBLE *x[MAX_CORNERS_OF_ELEM];
130 
131                                     ELEMENT* theElement = VFATHER(theVertex);
132                                     if (theElement == NULL) continue;
133                                     HEAPFAULT(theElement);
134                                     CORNER_COORDINATES(theElement,n,x);
135                                     UG_GlobalToLocal(n,(const DOUBLE **)x,
136                                                                      CVECT(theVertex),LCVECT(theVertex));
137                             }
138      */
139   }
140 
141   /* reconstruct VFATHER pointers and                */
142   /* make ghost neighborships symmetric (only for 3d)*/
143   /*
144    * Also: If there are SideVectors, set the VCOUNT field correctly (i.e., the number
145    * of elements that reference a given SideVector).  This information has been transferred as-is
146    * during load balancing, but may be wrong on new ghost elements.
147    */
148   for (ELEMENT* theElement = PFIRSTELEMENT(theGrid); theElement!=NULL; theElement=SUCCE(theElement))
149   {
150     /* This is the SideVector part */
151 #ifdef __THREEDIM__
152     if (VEC_DEF_IN_OBJ_OF_GRID(theGrid,SIDEVEC))
153       for (INT i=0; i<SIDES_OF_ELEM(theElement); i++)
154         SETVCOUNT(SVECTOR(theElement,i), (NBELEM(theElement,i) ? 2 : 1));
155 #endif
156 
157     /* Here comes the rest, all the way to the end of the element loop */
158 
159     /* TODO: delete now done in ElementObjMkCons()
160        #ifdef __THREEDIM__
161                     if (EVGHOST(theElement))
162                     {
163                             ELEMENT *NbElement;
164 
165                             for (INT i=0; i<SIDES_OF_ELEM(theElement); i++)
166                             {
167                                     NbElement = NBELEM(theElement,i);
168                                     for (j=0; j<SIDES_OF_ELEM(NbElement); j++)
169                                     {
170                                             if (NBELEM(NbElement,j) == theElement) break;
171                                     }
172                                     if (j>=SIDES_OF_ELEM(NbElement))
173                                             SET_NBELEM(theElement,i,NULL);
174                             }
175                     }
176        #endif
177      */
178 
179     ELEMENT* theFather = EFATHER(theElement);
180 
181     /* no reconstruction of VFATHER possible */
182     if (theFather == NULL) continue;
183 
184     for (INT i=0; i<CORNERS_OF_ELEM(theElement); i++)
185     {
186       NODE* theNode = CORNER(theElement,i);
187       if (CORNERTYPE(theNode)) continue;
188 
189       VERTEX* theVertex = MYVERTEX(theNode);
190 
191       /* this is too few for arbitrary load balancing, since
192               VFATHER pointer may have changed (970828 s.l.)
193                               if (VFATHER(theVertex)==NULL || EPRIO(VFATHER(theVertex))==PrioHGhost)
194        */
195       /* this is too few for arbitrary load balancing, since
196               VFATHER pointer may be already a zombie pointer (980126 s.l.)
197                               if (VFATHER(theVertex)==NULL || EPRIO(theFather)!=PrioHGhost)
198        */
199       {
200         switch (NTYPE(theNode))
201         {
202         case (MID_NODE) :
203         {
204           INT co0,co1;
205 
206           for (j=0; j<EDGES_OF_ELEM(theFather); j++)
207           {
208             theEdge = GetEdge(CORNER(theFather,CORNER_OF_EDGE(theFather,j,0)),
209                               CORNER(theFather,CORNER_OF_EDGE(theFather,j,1)));
210             if (MIDNODE(theEdge) == theNode) break;
211           }
212           /* here should be an assertion, but not in each situation the
213              midnode pointer is set (970829 s.l.)
214                                                           ASSERT(j<EDGES_OF_ELEM(theFather));
215            */
216           if (j>=EDGES_OF_ELEM(theFather))
217           {
218             for (j=0; j<EDGES_OF_ELEM(theFather); j++)
219             {
220               theEdge = GetEdge(CORNER(theFather,CORNER_OF_EDGE(theFather,j,0)),
221                                 CORNER(theFather,CORNER_OF_EDGE(theFather,j,1)));
222                                                                 #ifdef Debug
223               if (theEdge->midnode != NULL)
224                 PRINTDEBUG(dddif,1,
225                            (PFMT " ConstructConsistentGrid(): elem=" EID_FMTX
226                             " i=%d n1=" ID_FMTX " n2=" ID_FMTX " midnode= " ID_FMTX  "\n",
227                             me,theFather,EID_PRTX(theFather),j,
228                             ID_PRTX(NBNODE(LINK0(theEdge))),
229                             ID_PRTX(NBNODE(LINK1(theEdge))),
230                             ID_PRTX(theEdge->midnode)))
231                                                                 #endif
232             }
233 
234 
235 
236             PRINTDEBUG(dddif,1,
237                        ("ConstructConsistentGrid(): WARN "
238                         " theNode= " ID_FMTX
239                         " vertex= " VID_FMTX
240                         " recalculation of VFATHER impossible\n",
241                         ID_PRTX(NBNODE(LINK0(theEdge))),
242                         VID_PRTX(theVertex)));
243             /* if it couldn't  be recalculated reset it */
244             VFATHER(theVertex) = NULL;
245             break;
246           }
247 
248 
249           /* reconstruct local coordinates of vertex */
250           co0 = CORNER_OF_EDGE(theFather,j,0);
251           co1 = CORNER_OF_EDGE(theFather,j,1);
252 
253           /* local coordinates have to be local towards pe */
254 
255 
256           V_DIM_LINCOMB(0.5, LOCAL_COORD_OF_ELEM(theFather,co0),
257                         0.5, LOCAL_COORD_OF_ELEM(theFather,co1),
258                         LCVECT(theVertex));
259           SETONEDGE(theVertex,j);
260 
261           break;
262         }
263 
264                                         #ifdef __THREEDIM__
265         case (SIDE_NODE) :
266         {
267           /* always compute new coords for this case! */
268           INT k;
269           if (TAG(theFather) == PYRAMID) k=0;
270           else
271             k =  GetSideIDFromScratch(theElement,theNode);
272           ASSERT(k < SIDES_OF_ELEM(theFather));
273 
274           SETONSIDE(theVertex,k);
275 
276           INT m = CORNERS_OF_SIDE(theFather,k);
277           DOUBLE* local = LCVECT(theVertex);
278           DOUBLE fac = 1.0 / m;
279           V_DIM_CLEAR(local);
280           for (INT o=0; o<m; o++)
281           {
282             INT l = CORNER_OF_SIDE(theFather,k,o);
283             V_DIM_LINCOMB(1.0,local,1.0,
284                           LOCAL_COORD_OF_ELEM(theFather,l),local);
285           }
286           V_DIM_SCALE(fac,local);
287 
288           ELEMENT* theNb = NBELEM(theFather,k);
289           if (theNb != NULL)
290           {
291             for (j=0; j<SIDES_OF_ELEM(theNb); j++)
292             {
293               if (NBELEM(theNb,j) == theFather) break;
294             }
295             ASSERT(j < SIDES_OF_ELEM(theNb));
296             SETONNBSIDE(theVertex,j);
297           }
298           else SETONNBSIDE(theVertex,MAX_SIDES_OF_ELEM);
299           break;
300         }
301                                         #endif
302         case (CENTER_NODE) :
303         case (LEVEL_0_NODE) :
304           /* nothing to do */
305           break;
306 
307         case (CORNER_NODE) :
308         default :
309           assert(0);
310           break;
311         }
312 
313         VFATHER(theVertex) = theFather;
314 
315         if (OBJT(theVertex) == BVOBJ)
316           if (MOVED(theVertex)) {
317             INT n;
318             DOUBLE *x[MAX_CORNERS_OF_ELEM];
319 
320             CORNER_COORDINATES(theFather,n,x);
321             UG_GlobalToLocal(n,(const DOUBLE **)x,
322                              CVECT(theVertex),LCVECT(theVertex));
323           }
324       }
325     }
326   }
327 }
328 
329 /****************************************************************************/
330 /*
331    ConstructConsistentGrid -
332 
333    SYNOPSIS:
334    void ConstructConsistentGrid (GRID *theGrid);
335 
336    PARAMETERS:
337    .  theGrid
338 
339    DESCRIPTION:
340    Provide a consistent grid level. Do not call for a single grid level, but
341    always for the whole multigrid from bottom to top, since otherwise
342    consistency is not ensured!
343 
344    RETURN VALUE:
345    void
346  */
347 /****************************************************************************/
348 
ConstructConsistentGrid(GRID * theGrid)349 void NS_DIM_PREFIX ConstructConsistentGrid (GRID *theGrid)
350 {
351   /* the setting of the priorities has to be done in two waves after */
352   /* completion of the grid transfer, since                          */
353   /* - decisions about vghost prio can only be done if all sons are  */
354   /*   available in SetGhostObjectPriorities()                       */
355   /* - setting of the border priorities can only be done if all      */
356   /*   ghost objects have their proper priority                      */
357 
358   DDD_XferBegin(theGrid->dddContext());
359   SetGhostObjectPriorities(theGrid);
360   DDD_XferEnd(theGrid->dddContext());
361 
362   DDD_XferBegin(theGrid->dddContext());
363   SetBorderPriorities(theGrid);
364   DDD_XferEnd(theGrid->dddContext());
365 
366   ConstructConsistentGridLevel(theGrid);
367 }
368 
369 /****************************************************************************/
370 /*
371    ConstructConsistentMultiGrid -
372 
373    SYNOPSIS:
374    void ConstructConsistentMultiGrid (MULTIGRID *theMG);
375 
376    PARAMETERS:
377    .  theMG
378 
379    DESCRIPTION:
380    Provide a consistent multigrid.
381 
382    RETURN VALUE:
383    void
384  */
385 /****************************************************************************/
386 
ConstructConsistentMultiGrid(MULTIGRID * theMG)387 void NS_DIM_PREFIX ConstructConsistentMultiGrid (MULTIGRID *theMG)
388 {
389   INT l;
390 
391   /* this is done in three waves:   */
392   /* 1. set priorities of objects   */
393   /* 2. set border priorities       */
394   /* 3. repair grid inconsistencies */
395 
396   /* 1. set priorities of objects   */
397   DDD_XferBegin(theMG->dddContext());
398   for (l=0; l<=TOPLEVEL(theMG); l++)
399   {
400     GRID *theGrid = GRID_ON_LEVEL(theMG,l);
401     SetGhostObjectPriorities(theGrid);
402   }
403   DDD_XferEnd(theMG->dddContext());
404 
405   /* 2. set border priorities       */
406   DDD_XferBegin(theMG->dddContext());
407   for (l=0; l<=TOPLEVEL(theMG); l++)
408   {
409     GRID *theGrid = GRID_ON_LEVEL(theMG,l);
410     SetBorderPriorities(theGrid);
411   }
412   DDD_XferEnd(theMG->dddContext());
413 
414   /* 3. repair grid inconsistencies */
415   for (l=0; l<=TOPLEVEL(theMG); l++)
416   {
417     GRID *theGrid = GRID_ON_LEVEL(theMG,l);
418     ConstructConsistentGridLevel(theGrid);
419   }
420 
421 }
422 
423 #endif
424