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: overlap.c */
6 /* */
7 /* Purpose: management of grid overlap during adaption */
8 /* */
9 /* Author: Stefan Lang */
10 /* Institut fuer Computeranwendungen III */
11 /* Universitaet Stuttgart */
12 /* Pfaffenwaldring 27 */
13 /* 70569 Stuttgart */
14 /* */
15 /* History: 970204 sl begin */
16 /* */
17 /****************************************************************************/
18
19 #ifdef ModelP
20
21 /****************************************************************************/
22 /* */
23 /* include files */
24 /* system include files */
25 /* application include files */
26 /* */
27 /****************************************************************************/
28
29 /* standard C library */
30 #include <config.h>
31 #include <cassert>
32 #include <cmath>
33 #include <cstdio>
34 #include <cstdlib>
35 #include <cstring>
36
37 /* low module */
38 #include <dune/uggrid/low/debug.h>
39 #include <dune/uggrid/low/heaps.h>
40 #include <dune/uggrid/low/misc.h>
41 #include <dune/uggrid/low/namespace.h>
42 #include <dune/uggrid/low/ugtypes.h>
43
44 /* dev module */
45 #include <dune/uggrid/ugdevices.h>
46
47 /* gm module */
48 #include <dune/uggrid/gm/algebra.h>
49 #include <dune/uggrid/gm/evm.h>
50 #include <dune/uggrid/gm/gm.h>
51 #include <dune/uggrid/gm/pargm.h>
52 #include <dune/uggrid/gm/refine.h>
53 #include <dune/uggrid/gm/rm.h>
54 #include <dune/uggrid/gm/ugm.h>
55
56 /* parallel modules */
57 #include <dune/uggrid/parallel/ddd/include/ddd.h>
58 #include <dune/uggrid/parallel/ppif/ppif.h>
59 #include "identify.h"
60 #include "parallel.h"
61
62 /* UG namespaces: */
63 USING_UG_NAMESPACES
64
65 /* PPIF namespace: */
66 using namespace PPIF;
67
68 START_UGDIM_NAMESPACE
69
70 /****************************************************************************/
71 /* */
72 /* defines in the following order */
73 /* */
74 /* compile time constants defining static data size (i.e. arrays) */
75 /* other constants */
76 /* macros */
77 /* */
78 /****************************************************************************/
79
80 /* undefine if overlap should be only updated where needed */
81 /* This does not work since the connection of the overlap needs the
82 fatherelements on both sides (ghost and master sons) and this is
83 not ensured.
84 #define UPDATE_FULLOVERLAP
85 */
86
87 /****************************************************************************/
88 /* */
89 /* data structures used in this source file (exported data structures are */
90 /* in the corresponding include file!) */
91 /* */
92 /****************************************************************************/
93
94
95 /****************************************************************************/
96 /* */
97 /* definition of exported global variables */
98 /* */
99 /****************************************************************************/
100
101
102 /****************************************************************************/
103 /* */
104 /* definition of variables global to this source file only (static!) */
105 /* */
106 /****************************************************************************/
107
108
109 /****************************************************************************/
110 /* */
111 /* forward declarations of functions used before they are defined */
112 /* */
113 /****************************************************************************/
114
115
116 /****************************************************************************/
117 /*
118 UpdateElementOverlap -
119
120 SYNOPSIS:
121 static INT UpdateElementOverlap (ELEMENT *theElement);
122
123 PARAMETERS:
124 . theElement
125
126 DESCRIPTION:
127
128 RETURN VALUE:
129 INT
130 */
131 /****************************************************************************/
132
UpdateElementOverlap(DDD::DDDContext & context,ELEMENT * theElement)133 static INT UpdateElementOverlap (DDD::DDDContext& context, ELEMENT *theElement)
134 {
135 INT i,s,prio;
136 INT SonsOfSide,SonSides[MAX_SONS];
137 ELEMENT *theNeighbor,*theSon;
138 ELEMENT *SonList[MAX_SONS];
139
140 /* yellow_class specific code: */
141 /* update need to be done for all elements with THEFLAG set, */
142 /* execpt for yellow copies, since their neighbor need not be */
143 /* refined (s.l. 971029) */
144 #ifndef UPDATE_FULLOVERLAP
145 if (!THEFLAG(theElement) && REFINECLASS(theElement)!=YELLOW_CLASS) return(GM_OK);
146 #endif
147 /*
148 if (!THEFLAG(theElement)) return(GM_OK);
149 */
150
151 for (i=0; i<SIDES_OF_ELEM(theElement); i++)
152 {
153 theNeighbor = NBELEM(theElement,i);
154 if (theNeighbor == NULL) continue;
155
156 prio = EPRIO(theNeighbor);
157 if (!IS_REFINED(theNeighbor) || !EHGHOSTPRIO(prio)) continue;
158
159 /* yellow_class specific code: */
160 /* this is the special situation an update of the element overlap */
161 /* is needed, since the yellow element has now gotten a new yellow */
162 /* neighbor (s.l. 971029) */
163 /* sending of yellow copies is now done in each situation. To send */
164 /* a yellow copy only if needed, THEFLAG(theNeighbor) must be set */
165 /* properly in AdaptGrid() (980114 s.l.) */
166 #ifndef UPDATE_FULLOVERLAP
167 if ((REFINECLASS(theElement)==YELLOW_CLASS && !THEFLAG(theElement)) &&
168 !THEFLAG(theNeighbor)) continue;
169 #endif
170
171 PRINTDEBUG(gm,1,("%d: EID=%d side=%d NbID=%d " "NbPARTITION=%d\n",me,
172 ID(theElement),i,ID(theNeighbor), EPROCPRIO(context, theNeighbor,PrioMaster)))
173
174 Get_Sons_of_ElementSide(theElement,i,&SonsOfSide,
175 SonList,SonSides,1,0);
176 PRINTDEBUG(gm,1,("%d: SonsOfSide=%d\n",me,SonsOfSide))
177
178 for (s=0; s<SonsOfSide; s++)
179 {
180 theSon = SonList[s];
181 ASSERT(theSon != NULL);
182
183 PRINTDEBUG(gm,1,("%d: Sending Son=%08x/%x SonID=%d "
184 "SonLevel=%d to dest=%d\n", me,EGID(theSon),theSon,
185 ID(theSon),LEVEL(theSon), EPROCPRIO(context, theNeighbor,PrioMaster)))
186
187 if (EPROCPRIO(context, theNeighbor,PrioMaster)>=context.procs()) break;
188
189 XFERECOPYX(context, theSon,EPROCPRIO(context, theNeighbor,PrioMaster),PrioHGhost,
190 (OBJT(theSon)==BEOBJ) ? BND_SIZE_TAG(TAG(theSon)) :
191 INNER_SIZE_TAG(TAG(theSon)));
192 /* send son to all elements where theNeighbor is master, vghost or vhghost */
193 if (0)
194 {
195 int *proclist = EPROCLIST(context, theNeighbor);
196 proclist += 2;
197 while (*proclist != -1)
198 {
199 if (!EHGHOSTPRIO(*(proclist+1)))
200 {
201 XFERECOPYX(context, theSon,*proclist,PrioHGhost,
202 (OBJT(theSon)==BEOBJ) ? BND_SIZE_TAG(TAG(theSon)) :
203 INNER_SIZE_TAG(TAG(theSon)));
204 }
205 proclist += 2;
206 }
207 }
208 }
209 }
210
211 return(GM_OK);
212 }
213
214 /****************************************************************************/
215 /*
216 UpdateGridOverlap -
217
218 SYNOPSIS:
219 INT UpdateGridOverlap (GRID *theGrid);
220
221 PARAMETERS:
222 . theGrid
223
224 DESCRIPTION:
225
226 RETURN VALUE:
227 INT
228 */
229 /****************************************************************************/
230
UpdateGridOverlap(GRID * theGrid)231 INT UpdateGridOverlap (GRID *theGrid)
232 {
233 DDD::DDDContext& context = theGrid->dddContext();
234 ELEMENT *theElement;
235
236 for (theElement=FIRSTELEMENT(theGrid); theElement!=NULL; theElement=SUCCE(theElement))
237 {
238 if (IS_REFINED(theElement))
239 UpdateElementOverlap(context, theElement);
240 }
241
242 return(GM_OK);
243 }
244
245
246 /****************************************************************************/
247 /*
248 UpdateMultiGridOverlap -
249
250 SYNOPSIS:
251 static INT UpdateMultiGridOverlap (MULTIGRID *theMG, INT FromLevel);
252
253 PARAMETERS:
254 . theMG
255 . FromLevel
256
257 DESCRIPTION:
258
259 RETURN VALUE:
260 INT
261 */
262 /****************************************************************************/
263
UpdateMultiGridOverlap(MULTIGRID * theMG,INT FromLevel)264 static INT UpdateMultiGridOverlap (MULTIGRID *theMG, INT FromLevel)
265 {
266 INT l;
267 GRID *theGrid;
268
269 ddd_HandlerInit(theMG->dddContext(), HSET_REFINE);
270
271 for (l=FromLevel; l<TOPLEVEL(theMG); l++)
272 {
273 theGrid = GRID_ON_LEVEL(theMG,l);
274 UpdateGridOverlap(theGrid);
275 }
276
277 return(GM_OK);
278 }
279
280
281 /****************************************************************************/
282 /*
283 DropUsedFlags -
284
285 SYNOPSIS:
286 static INT DropUsedFlags (GRID *theGrid);
287
288 PARAMETERS:
289 . theGrid
290
291 DESCRIPTION:
292
293 RETURN VALUE:
294 INT
295 */
296 /****************************************************************************/
297
DropUsedFlags(GRID * theGrid)298 static INT DropUsedFlags (GRID *theGrid)
299 {
300 ELEMENT *theElement;
301
302 for (theElement=PFIRSTELEMENT(theGrid); theElement!=NULL; theElement=SUCCE(theElement))
303 {
304 if (USED(theElement) == 1)
305 {
306 REFINE_ELEMENT_LIST(1,theElement,"drop mark");
307
308 ASSERT(EFATHER(theElement)!=NULL);
309
310 /* this father has to be connected */
311 SETUSED(EFATHER(theElement),1);
312 SETUSED(theElement,0);
313 }
314 }
315
316 return(GM_OK);
317 }
318
319
320 /****************************************************************************/
321 /*
322 ConnectGridOverlap -
323
324 SYNOPSIS:
325 INT ConnectGridOverlap (GRID *theGrid);
326
327 PARAMETERS:
328 . theGrid
329
330 DESCRIPTION:
331
332 RETURN VALUE:
333 INT
334 */
335 /****************************************************************************/
336
ConnectGridOverlap(GRID * theGrid)337 INT ConnectGridOverlap (GRID *theGrid)
338 {
339 INT i,j,Sons_of_Side,prio;
340 INT SonSides[MAX_SIDE_NODES];
341 ELEMENT *theElement;
342 ELEMENT *theNeighbor;
343 ELEMENT *theSon;
344 ELEMENT *Sons_of_Side_List[MAX_SONS];
345
346 for (theElement=PFIRSTELEMENT(theGrid); theElement!=NULL; theElement=SUCCE(theElement))
347 {
348 prio = EPRIO(theElement);
349
350 /* connect only FROM hgost copies */
351 if (!IS_REFINED(theElement) || !EHGHOSTPRIO(prio)) continue;
352
353 PRINTDEBUG(gm,1,("Connecting e=%08x/%x ID=%d eLevel=%d\n",
354 DDD_InfoGlobalId(PARHDRE(theElement)),
355 theElement,ID(theElement),
356 LEVEL(theElement)));
357
358 for (i=0; i<SIDES_OF_ELEM(theElement); i++)
359 {
360 if (OBJT(theElement)==BEOBJ
361 && SIDE_ON_BND(theElement,i)
362 && !INNER_BOUNDARY(theElement,i)) continue;
363
364 theNeighbor = NBELEM(theElement,i);
365 if (theNeighbor == NULL) continue;
366
367 prio = EPRIO(theNeighbor);
368 /* overlap situation hasn't changed */
369 if (!THEFLAG(theElement) && !THEFLAG(theNeighbor)) continue;
370
371 /* connect only TO master copies */
372 #ifdef __TWODIM__
373 if (!IS_REFINED(theNeighbor) || !MASTERPRIO(prio)) continue;
374 #endif
375 #ifdef __THREEDIM__
376 if (!IS_REFINED(theNeighbor)) continue;
377 #endif
378
379 if (Get_Sons_of_ElementSide(theElement,i,&Sons_of_Side,
380 Sons_of_Side_List,SonSides,1,0)!=GM_OK) RETURN(GM_FATAL);
381
382 IFDEBUG(gm,1)
383 UserWriteF(" side=%d NSONS=%d Sons_of_Side=%d:\n",
384 i,NSONS(theElement),Sons_of_Side);
385 for (j=0; j<Sons_of_Side; j++)
386 UserWriteF(" son=%08x/%x sonside=%d\n",
387 EGID(Sons_of_Side_List[j]),
388 Sons_of_Side_List[j],SonSides[j]);
389 printf(" connecting ghostelements:\n");
390 ENDDEBUG
391
392 /* the ioflag=1 is needed, since not all sended ghosts are needed! */
393 if (Connect_Sons_of_ElementSide(theGrid,theElement,i,
394 Sons_of_Side,Sons_of_Side_List,SonSides,1)!=GM_OK)
395 RETURN(GM_FATAL);
396 }
397
398 /* 1. yellow_class specific code: */
399 /* check whether is a valid ghost, which as in minimum one */
400 /* master element as neighbor */
401 /* TODO: move this functionality to ComputeCopies */
402 /* then disposing of theSon can be done in AdaptGrid */
403 /* and the extra Xfer env around ConnectGridOverlap() */
404 /* can be deleted (s.l. 971029) */
405
406 /* 2. ghost-ghost neighborship specific code: */
407 /* reset in 3D all unsymmetric neighbor relationships */
408 /* to avoid referencing of zombie pointers. */
409 /* this happened e.g. in CorrectElementSidePattern() */
410 /* (s.l. 980223) */
411 {
412 ELEMENT *SonList[MAX_SONS];
413
414 GetAllSons(theElement,SonList);
415 for (i=0; SonList[i]!=NULL; i++)
416 {
417 INT ok = 0;
418 theSon = SonList[i];
419 if (!EHGHOST(theSon)) continue;
420 for (j=0; j<SIDES_OF_ELEM(theSon); j++)
421 {
422 ELEMENT *NbSon = NBELEM(theSon,j);
423
424 if (NbSon == NULL) continue;
425
426 if (EMASTER(NbSon))
427 {
428 ok = 1;
429 }
430 /* reset unsymmetric pointer relation ship */
431 /* TODO: delete this is done in ElementObjMkCons()
432 else
433 {
434 INT k;
435 for (k=0; k<SIDES_OF_ELEM(NbSon); k++)
436 {
437 if (NBELEM(NbSon,k)==theSon) break;
438 }
439 if (k>=SIDES_OF_ELEM(NbSon)) SET_NBELEM(theSon,j,NULL);
440 }
441 */
442 }
443 if (!ok)
444 {
445 if (ECLASS(theSon) == YELLOW_CLASS)
446 {
447 UserWriteF("ConnectGridOverlap(): disposing useless yellow ghost e=" EID_FMTX
448 "f=" EID_FMTX "this ghost is useless!\n",
449 EID_PRTX(theSon),EID_PRTX(theElement));
450 DisposeElement(UPGRID(theGrid),theSon,true);
451 }
452 else
453 {
454 UserWriteF("ConnectGridOverlap(): ERROR e=" EID_FMTX
455 "f=" EID_FMTX "this ghost is useless!\n",
456 EID_PRTX(theSon),EID_PRTX(theElement));
457
458 /* TODO: better do this
459 assert(0); */
460 }
461 }
462 }
463 }
464 }
465
466 return(GM_OK);
467 }
468
469
470
471 /****************************************************************************/
472 /*
473 ConnectMultiGridOverlap -
474
475 SYNOPSIS:
476 static INT ConnectMultiGridOverlap (MULTIGRID *theMG, INT FromLevel);
477
478 PARAMETERS:
479 . theMG
480 . FromLevel
481
482 DESCRIPTION:
483
484 RETURN VALUE:
485 INT
486 */
487 /****************************************************************************/
488
ConnectMultiGridOverlap(MULTIGRID * theMG,INT FromLevel)489 static INT ConnectMultiGridOverlap (MULTIGRID *theMG, INT FromLevel)
490 {
491 INT l;
492 GRID *theGrid;
493
494 /* drop used marks to fathers */
495 for (l=FromLevel+1; l<=TOPLEVEL(theMG); l++)
496 {
497 theGrid = GRID_ON_LEVEL(theMG,l);
498 if (DropUsedFlags(theGrid)) RETURN(GM_FATAL);
499 }
500
501 /* connect sons of elements with used flag set */
502 for (l=FromLevel; l<TOPLEVEL(theMG); l++)
503 {
504
505 theGrid = GRID_ON_LEVEL(theMG,l);
506 if (ConnectGridOverlap(theGrid)) RETURN(GM_FATAL);
507 }
508
509 return(GM_OK);
510 }
511
512
513 /****************************************************************************/
514 /*
515 ConnectVerticalOverlap - reconstruct fathers and sons of HGHOSTS
516
517 SYNOPSIS:
518 INT ConnectVerticalOverlap (MULTIGRID *theMG);
519
520 PARAMETERS:
521 . theMG - pointer to multigrid
522
523 DESCRIPTION:
524 IO and Loadbalancing to not consider father-son relations of HGHOSTS;
525 here, this information is reconstructed.
526
527 RETURN VALUE:
528 INT
529
530 GM_OK if ok.
531 */
532 /****************************************************************************/
533
CompareSide(ELEMENT * theElement,INT s,ELEMENT * theFather,INT t)534 static INT CompareSide (ELEMENT *theElement, INT s, ELEMENT *theFather, INT t)
535 {
536 NODE *Nodes[MAX_SIDE_NODES];
537 INT n;
538 INT m = CORNERS_OF_SIDE(theElement,s);
539 INT k = 0;
540 INT i,j;
541
542 GetSonSideNodes(theFather,t,&n,Nodes,0);
543
544 for (i=0; i<m; i++)
545 {
546 NODE *theNode = CORNER(theElement,CORNER_OF_SIDE(theElement,s,i));
547
548 for (j=0; j<MAX_SIDE_NODES; j++)
549 if (theNode == Nodes[j]) {
550 k++;
551 break;
552 }
553 }
554
555 return((k == m));
556 }
557
ConnectVerticalOverlap(MULTIGRID * theMG)558 INT ConnectVerticalOverlap (MULTIGRID *theMG)
559 {
560 INT l;
561
562 for (l=1; l<=TOPLEVEL(theMG); l++)
563 {
564 GRID *theGrid = GRID_ON_LEVEL(theMG,l);
565 ELEMENT *theElement;
566
567 for (theElement=PFIRSTELEMENT(theGrid);
568 theElement!=NULL; theElement=SUCCE(theElement))
569 {
570 INT prio = EPRIO(theElement);
571 INT neflag = NO;
572 INT i;
573
574 if (prio == PrioMaster) break;
575 if (prio == PrioVGhost) continue;
576 if (EFATHER(theElement) != NULL) continue;
577 for (i=0; i<SIDES_OF_ELEM(theElement); i++)
578 {
579 ELEMENT *theNeighbor = NBELEM(theElement,i);
580
581 if (theNeighbor == NULL) continue;
582 if (EMASTER(theNeighbor))
583 {
584 ELEMENT *theFather = EFATHER(theNeighbor);
585 INT j;
586
587 ASSERT(theFather != NULL);
588 for (j=0; j<SIDES_OF_ELEM(theFather); j++)
589 {
590 ELEMENT *el = NBELEM(theFather,j);
591
592 if (el == NULL) continue;
593 if (EMASTER(el)) continue;
594 if (EVGHOST(el)) continue;
595 if (CompareSide(theElement,i,theFather,j))
596 {
597 INT where = PRIO2INDEX(EPRIO(theElement));
598 PRINTDEBUG(dddif,0,(PFMT " ConnectVerticalOverlap "
599 " e=" EID_FMTX
600 " n=" EID_FMTX
601 " nf=" EID_FMTX
602 " f=" EID_FMTX "\n",
603 me,
604 EID_PRTX(theElement),
605 EID_PRTX(theNeighbor),
606 EID_PRTX(theFather),
607 EID_PRTX(el)));
608 SET_EFATHER(theElement,el);
609 if (NSONS(el) == 0)
610 {
611 SET_SON(el,where,theElement);
612 /* Father found, hence exit loop. Otherwise multiple fixes lead to element list inconsistency
613 and endless element loop */
614 /* Achim 030506 */
615 neflag = YES;
616 break;
617 }
618 else
619 {
620 ELEMENT *theSon = SON(el,where);
621
622 assert(PRIO2INDEX(EPRIO(theSon)) == where);
623 GRID_UNLINK_ELEMENT(theGrid,theElement);
624 GRID_LINKX_ELEMENT(theGrid,theElement,
625 EPRIO(theElement),theSon);
626 /* Father found, hence exit loop. Otherwise multiple fixes lead to element list inconsistency
627 and endless element loop */
628 /* Achim 030506 */
629 neflag = YES;
630 break;
631 }
632 SETNSONS(el,NSONS(el)+1);
633 }
634 }
635 /* Father found, hence exit loop. Otherwise multiple fixes lead to element list inconsistency
636 and endless element loop */
637 /* Achim 030506 */
638 if (neflag == YES)
639 break;
640 }
641 }
642 }
643 }
644
645 return(GM_OK);
646 }
647
ConnectOverlapVerticalGrid(GRID * theGrid)648 static INT ConnectOverlapVerticalGrid (GRID *theGrid)
649 {
650 INT i,j,k,found,edgenode0,edgenode1;
651 ELEMENT *theElement,*theSon,*SonList[MAX_SONS];
652 NODE *theNode,*SonNode,*FatherNode,*EdgeNode0,*EdgeNode1;
653 EDGE *theEdge,*FatherEdge;
654 VERTEX *theVertex;
655 DOUBLE *songlobal,diff;
656 DOUBLE_VECTOR global;
657
658 for (theElement=PFIRSTELEMENT(theGrid); theElement!=NULL; theElement=SUCCE(theElement))
659 {
660 /* reconstuct node relations using element relations */
661 if (GetAllSons(theElement,SonList) != GM_OK) REP_ERR_RETURN(1);
662 for (i=0; SonList[i]!=NULL; i++)
663 {
664 theSon = SonList[i];
665 for (j=0; j<CORNERS_OF_ELEM(theSon); j++)
666 {
667 found = 0;
668 SonNode = CORNER(theSon,j);
669 switch(NTYPE(SonNode))
670 {
671 case CORNER_NODE :
672 FatherNode = (NODE *) NFATHER(SonNode);
673 if (FatherNode != NULL)
674 {
675 assert(SONNODE(FatherNode) == SonNode);
676 break;
677 }
678 assert(!MOVED(MYVERTEX(SonNode)));
679 for (k=0; k<CORNERS_OF_ELEM(theElement); k++)
680 {
681 theNode = CORNER(theElement,k);
682 if (MYVERTEX(theNode) == MYVERTEX(SonNode))
683 {
684 assert(found == 0);
685 assert (SONNODE(theNode)==NULL ||
686 SONNODE(theNode) == SonNode);
687 printf("ConnectOverlapVerticalGrid(): new "
688 " sonnode relation between theNode=" ID_FMTX
689 " SonNode=" ID_FMTX "\n",
690 ID_PRTX(theNode),ID_PRTX(SonNode));
691 SETNFATHER(SonNode,(GEOM_OBJECT *)theNode);
692 SONNODE(theNode) = SonNode;
693 found ++;
694 }
695 }
696 break;
697 case MID_NODE :
698 FatherEdge = (EDGE *) NFATHER(SonNode);
699 if (FatherEdge != NULL)
700 {
701 assert(MIDNODE(FatherEdge) == SonNode);
702 break;
703 }
704 assert(!MOVED(MYVERTEX(SonNode)));
705 for (k=0; k<EDGES_OF_ELEM(theElement); k++)
706 {
707 edgenode0 = CORNER_OF_EDGE(theElement,k,0);
708 edgenode1 = CORNER_OF_EDGE(theElement,k,1);
709 EdgeNode0 = CORNER(theElement,edgenode0);
710 EdgeNode1 = CORNER(theElement,edgenode1);
711 assert(EdgeNode0!=NULL && EdgeNode1!=NULL);
712
713 theEdge = GetEdge(EdgeNode0,EdgeNode1);
714 assert(theEdge != NULL);
715 songlobal = CVECT(MYVERTEX(SonNode));
716 V_DIM_LINCOMB(0.5, CVECT(MYVERTEX(EdgeNode0)),
717 0.5, CVECT(MYVERTEX(EdgeNode1)),global);
718 V_DIM_EUKLIDNORM_OF_DIFF(songlobal,global,diff);
719 if (diff <= MAX_PAR_DIST)
720 {
721 assert(found == 0);
722 assert (MIDNODE(theEdge)==NULL ||
723 MIDNODE(theEdge) == SonNode);
724
725 #ifdef __TWODIM__
726 IFDEBUG(dddif,1)
727 printf("ConnectOverlapVerticalGrid(): new "
728 " midnode relation between theEdge=%p"
729 " SonNode=" ID_FMTX "Vertex=" VID_FMTX "\n",
730 (void*) theEdge,ID_PRTX(SonNode),
731 VID_PRTX(MYVERTEX(SonNode)));
732 ENDDEBUG
733 #endif
734 #ifdef __THREEDIM__
735 printf("ConnectOverlapVerticalGrid(): new "
736 " midnode relation between theEdge=" ID_FMTX
737 " SonNode=" ID_FMTX "\n",
738 ID_PRTX(theEdge),ID_PRTX(SonNode));
739 #endif
740 SETNFATHER(SonNode,(GEOM_OBJECT *)theEdge);
741 MIDNODE(theEdge) = SonNode;
742 found ++;
743
744 /* reconstruct vertex information */
745 theVertex = MYVERTEX(SonNode);
746 V_DIM_LINCOMB(0.5, LOCAL_COORD_OF_ELEM(theElement,edgenode0),
747 0.5, LOCAL_COORD_OF_ELEM(theElement,edgenode1),
748 LCVECT(theVertex));
749 SETONEDGE(theVertex,k);
750 VFATHER(theVertex) = theElement;
751 }
752 }
753 break;
754 case SIDE_NODE :
755 case CENTER_NODE :
756 /* do nothing */
757 break;
758 default :
759 assert(0);
760 }
761 }
762 }
763 }
764
765 return(GM_OK);
766 }
767
ConnectOverlapVerticalMultiGrid(MULTIGRID * theMG)768 static INT ConnectOverlapVerticalMultiGrid (MULTIGRID *theMG)
769 {
770 INT i;
771 GRID *theGrid;
772
773 for (i=0; i<=TOPLEVEL(theMG); i++)
774 {
775 theGrid = GRID_ON_LEVEL(theMG,i);
776 if (ConnectOverlapVerticalGrid(theGrid)) return(GM_ERROR);
777 }
778 return(GM_OK);
779 }
780
781 END_UGDIM_NAMESPACE
782
783 #endif
784