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