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