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:	  trans.c                                                                                                       */
6 /*																			*/
7 /* Purpose:   create new grid distribution according to lb-marks of master  */
8 /*            elements.                                                                                                 */
9 /*																			*/
10 /* Author:	  Klaus Birken, Stefan Lang                                                             */
11 /*			  Institut fuer Computeranwendungen III                                                 */
12 /*			  Universitaet Stuttgart										*/
13 /*			  Pfaffenwaldring 27											*/
14 /*			  70569 Stuttgart												*/
15 /*			  email: ug@ica3.uni-stuttgart.de								*/
16 /*																			*/
17 /* History:   961216 kb  begin                                                                          */
18 /*																			*/
19 /* Remarks:                                                                                                                             */
20 /*																			*/
21 /****************************************************************************/
22 
23 
24 #ifdef ModelP
25 
26 /****************************************************************************/
27 /*																			*/
28 /* include files															*/
29 /*			  system include files											*/
30 /*			  application include files                                                                     */
31 /*																			*/
32 /****************************************************************************/
33 
34 #include <config.h>
35 #include <cassert>
36 
37 #include <dune/uggrid/parallel/ppif/ppifcontext.hh>
38 
39 #include "parallel.h"
40 #include <dune/uggrid/ugdevices.h>
41 #include <dune/uggrid/domain/domain.h>
42 #include <dune/uggrid/gm/algebra.h>
43 #include <dune/uggrid/gm/evm.h>
44 #include <dune/uggrid/gm/gm.h>
45 #include <dune/uggrid/gm/mgheapmgr.h>
46 #include <dune/uggrid/gm/refine.h>
47 #include <dune/uggrid/gm/ugm.h>
48 #include <dune/uggrid/low/debug.h>
49 #include <dune/uggrid/low/namespace.h>
50 #include <dune/uggrid/low/ugtime.h>
51 #include <dune/uggrid/low/ugtypes.h>
52 
53 /* UG namespaces: */
54 USING_UG_NAMESPACES
55 
56 /* PPIF namespace: */
57 using namespace PPIF;
58 
59 /****************************************************************************/
60 /*																			*/
61 /* defines in the following order											*/
62 /*																			*/
63 /*		  compile time constants defining static data size (i.e. arrays)	*/
64 /*		  other constants													*/
65 /*		  macros															*/
66 /*																			*/
67 /****************************************************************************/
68 
69 enum GhostCmds { GC_Keep, GC_ToMaster, GC_Delete };
70 
71 
72 #define XferElement(context, elem,dest,prio)                             \
73   { PRINTDEBUG(dddif,1,("%4d: XferElement(): XferCopy elem=" EID_FMTX " dest=%d prio=%d\n", \
74                         me,EID_PRTX(elem), dest, prio)); \
75     XFERECOPYX(context, (elem), dest, prio,               \
76                (OBJT(elem)==BEOBJ) ?   \
77                BND_SIZE_TAG(TAG(elem)) :   \
78                INNER_SIZE_TAG(TAG(elem)));  }
79 
80 #ifdef DDD_PRIO_ENV
81 #undef DDD_PrioritySet
82 #endif
83 
84 /****************************************************************************/
85 /*																			*/
86 /* data structures used in this source file (exported data structures are	*/
87 /*		  in the corresponding include file!)								*/
88 /*																			*/
89 /****************************************************************************/
90 
91 
92 /****************************************************************************/
93 /*																			*/
94 /* definition of exported global variables									*/
95 /*																			*/
96 /****************************************************************************/
97 
98 
99 /****************************************************************************/
100 /*																			*/
101 /* definition of variables global to this source file only (static!)		*/
102 /*																			*/
103 /****************************************************************************/
104 
105 
106 /****************************************************************************/
107 /*																			*/
108 /* forward declarations of functions used before they are defined			*/
109 /*																			*/
110 /****************************************************************************/
111 
112 /****************************************************************************/
113 
114 
115 
116 /****************************************************************************/
117 /*
118    Gather_ElemDest -
119 
120    SYNOPSIS:
121    static int Gather_ElemDest (DDD_OBJ obj, void *data);
122 
123    PARAMETERS:
124    .  obj
125    .  data
126 
127    DESCRIPTION:
128 
129    RETURN VALUE:
130    int
131  */
132 /****************************************************************************/
133 
Gather_ElemDest(DDD::DDDContext &,DDD_OBJ obj,void * data)134 static int Gather_ElemDest (DDD::DDDContext&, DDD_OBJ obj, void *data)
135 {
136   ELEMENT *theElement = (ELEMENT *)obj;
137 
138   *(DDD_PROC *)data = PARTITION(theElement);
139 
140   return 0;
141 }
142 
143 
144 /****************************************************************************/
145 /*
146    Scatter_ElemDest -
147 
148    SYNOPSIS:
149    static int Scatter_ElemDest (DDD_OBJ obj, void *data);
150 
151    PARAMETERS:
152    .  obj
153    .  data
154 
155    DESCRIPTION:
156 
157    RETURN VALUE:
158    int
159  */
160 /****************************************************************************/
161 
Scatter_ElemDest(DDD::DDDContext &,DDD_OBJ obj,void * data)162 static int Scatter_ElemDest (DDD::DDDContext&, DDD_OBJ obj, void *data)
163 {
164   ELEMENT *theElement = (ELEMENT *)obj;
165 
166   PARTITION(theElement) = *(DDD_PROC *)data;
167 
168   return 0;
169 }
170 
171 
172 /****************************************************************************/
173 /*
174    UpdateGhostDests -
175 
176    SYNOPSIS:
177    static int UpdateGhostDests (MULTIGRID *theMG);
178 
179    PARAMETERS:
180    .  theMG
181 
182    DESCRIPTION:
183 
184    RETURN VALUE:
185    int
186  */
187 /****************************************************************************/
188 
UpdateGhostDests(MULTIGRID * theMG)189 static int UpdateGhostDests (MULTIGRID *theMG)
190 {
191   auto& context = theMG->dddContext();
192   const auto& dddctrl = ddd_ctrl(context);
193 
194   DDD_IFOneway(context,
195                dddctrl.ElementIF, IF_FORWARD, sizeof(DDD_PROC),
196                Gather_ElemDest, Scatter_ElemDest);
197 
198   DDD_IFOneway(context,
199                dddctrl.ElementVIF, IF_FORWARD, sizeof(DDD_PROC),
200                Gather_ElemDest, Scatter_ElemDest);
201 
202   return 0;
203 }
204 
205 
206 
207 /****************************************************************************/
208 
209 
210 /****************************************************************************/
211 /*
212    Gather_GhostCmd -
213 
214    SYNOPSIS:
215    static int Gather_GhostCmd (DDD_OBJ obj, void *data, DDD_PROC proc, DDD_PRIO prio);
216 
217    PARAMETERS:
218    .  obj
219    .  data
220    .  proc
221    .  prio
222 
223    DESCRIPTION:
224 
225    RETURN VALUE:
226    int
227  */
228 /****************************************************************************/
229 
Gather_GhostCmd(DDD::DDDContext &,DDD_OBJ obj,void * data,DDD_PROC proc,DDD_PRIO prio)230 static int Gather_GhostCmd (DDD::DDDContext&, DDD_OBJ obj, void *data, DDD_PROC proc, DDD_PRIO prio)
231 {
232   ELEMENT *theElement = (ELEMENT *)obj;
233   INT j;
234 
235   /* TODO: not needed anymore. kb 9070108 */
236   if (PARTITION(theElement) == proc)
237   {
238     *((int *)data) = GC_ToMaster;
239 
240     return(0);
241   }
242 
243   if (PARTITION(theElement) != proc)
244   {
245     *((int *)data) = GC_Delete;
246 
247     for(j=0; j<SIDES_OF_ELEM(theElement); j++)
248     {
249       ELEMENT *nb = NBELEM(theElement,j);
250 
251       if (nb!=NULL)
252       {
253         if (PARTITION(nb)==proc)
254         {
255           *((int *)data) = GC_Keep;
256           break;
257         }
258       }
259     }
260     return(0);
261   }
262 
263   return(1);
264 }
265 
266 
267 /****************************************************************************/
268 /*
269    Scatter_GhostCmd -
270 
271    SYNOPSIS:
272    static int Scatter_GhostCmd (DDD_OBJ obj, void *data, DDD_PROC proc, DDD_PRIO prio);
273 
274    PARAMETERS:
275    .  obj
276    .  data
277    .  proc
278    .  prio
279 
280    DESCRIPTION:
281 
282    RETURN VALUE:
283    int
284  */
285 /****************************************************************************/
286 
Scatter_GhostCmd(DDD::DDDContext & context,DDD_OBJ obj,void * data,DDD_PROC proc,DDD_PRIO prio)287 static int Scatter_GhostCmd (DDD::DDDContext& context, DDD_OBJ obj, void *data, DDD_PROC proc, DDD_PRIO prio)
288 {
289   ELEMENT *theElement = (ELEMENT *)obj;
290   ELEMENT *SonList[MAX_SONS];
291   INT i;
292 
293   const auto& me = context.me();
294 
295   switch (*(int *)data)
296   {
297   case GC_Keep :
298     /* do nothing */
299     break;
300 
301   case GC_ToMaster :
302     /* TODO: not needed anymore. kb 9070108
303                             SETEPRIO(theElement, PrioMaster);*/
304     break;
305 
306   case GC_Delete :
307     if (NSONS(theElement) > 0)
308     {
309       if (GetAllSons(theElement,SonList) != 0) return(1);
310       i = 0;
311       while (SonList[i] != NULL)
312       {
313         if (PARTITION(SonList[i]) == me) return(0);
314         i++;
315       }
316     }
317     XFEREDELETE(context, theElement);
318     break;
319 
320   default :
321     assert(1);
322   }
323 
324   return(0);
325 }
326 
327 
328 /****************************************************************************/
329 /*
330    Gather_VHGhostCmd -
331 
332    SYNOPSIS:
333    static int Gather_VHGhostCmd (DDD_OBJ obj, void *data, DDD_PROC proc, DDD_PRIO prio);
334 
335    PARAMETERS:
336    .  obj
337    .  data
338    .  proc
339    .  prio
340 
341    DESCRIPTION:
342 
343    RETURN VALUE:
344    int
345  */
346 /****************************************************************************/
347 
Gather_VHGhostCmd(DDD::DDDContext &,DDD_OBJ obj,void * data,DDD_PROC proc,DDD_PRIO prio)348 static int Gather_VHGhostCmd (DDD::DDDContext&, DDD_OBJ obj, void *data, DDD_PROC proc, DDD_PRIO prio)
349 {
350   ELEMENT *theElement = (ELEMENT *)obj;
351   // ELEMENT *theFather      = EFATHER(theElement);
352   ELEMENT *theNeighbor;
353   INT j;
354 
355   if (PARTITION(theElement) != proc)
356   {
357     *((int *)data) = GC_Delete;
358 
359     for(j=0; j<SIDES_OF_ELEM(theElement); j++)
360     {
361       theNeighbor = NBELEM(theElement,j);
362 
363       if (theNeighbor != NULL)
364       {
365         if (PARTITION(theNeighbor) == proc)
366         {
367           *((int *)data) = GC_Keep;
368           return (0);
369         }
370       }
371     }
372 
373     /* wrong:		if (LEVEL(theElement) > 0)
374                     {
375                             ASSERT(theFather != NULL);
376 
377                             if (PARTITION(theFather) == proc)
378                             {
379        *((int *)data) = GC_Keep;
380                                     return (0);
381                             }
382                     } */
383     return (0);
384   }
385 
386   return(1);
387 }
388 
389 
390 /****************************************************************************/
391 /*
392    Scatter_VHGhostCmd -
393 
394    SYNOPSIS:
395    static int Scatter_VHGhostCmd (DDD_OBJ obj, void *data, DDD_PROC proc, DDD_PRIO prio);
396 
397    PARAMETERS:
398    .  obj
399    .  data
400    .  proc
401    .  prio
402 
403    DESCRIPTION:
404 
405    RETURN VALUE:
406    int
407  */
408 /****************************************************************************/
409 
Scatter_VHGhostCmd(DDD::DDDContext & context,DDD_OBJ obj,void * data,DDD_PROC proc,DDD_PRIO prio)410 static int Scatter_VHGhostCmd (DDD::DDDContext& context, DDD_OBJ obj, void *data, DDD_PROC proc, DDD_PRIO prio)
411 {
412   const auto& me = context.me();
413 
414   ELEMENT *theElement = (ELEMENT *)obj;
415   ELEMENT *SonList[MAX_SONS];
416 
417   /* if element is needed after transfer here */
418   if ((*(int *)data) == GC_Keep) return(0);
419 
420   /* element becomes master copy */
421   if (PARTITION(theElement) == me) return(0);
422 
423   /* if a son resides as master keep element as vghost */
424   if (GetAllSons(theElement,SonList) != GM_OK) return(0);
425   INT i = 0;
426   while (SonList[i] != NULL)
427   {
428     if (PARTITION(SonList[i]) == me) return(0);
429     i++;
430   }
431   /* element is not needed on me any more */
432   if ((*(int *)data) == GC_Delete)
433   {
434     XFEREDELETE(context, theElement);
435     return(0);
436   }
437 
438   return(1);
439 }
440 
441 
442 /****************************************************************************/
443 /*
444    ComputeGhostCmds -
445 
446    SYNOPSIS:
447    static int ComputeGhostCmds (MULTIGRID *theMG);
448 
449    PARAMETERS:
450    .  theMG
451 
452    DESCRIPTION:
453 
454    RETURN VALUE:
455    int
456  */
457 /****************************************************************************/
458 
ComputeGhostCmds(MULTIGRID * theMG)459 static int ComputeGhostCmds (MULTIGRID *theMG)
460 {
461   auto& context = theMG->dddContext();
462   const auto& dddctrl = ddd_ctrl(context);
463 
464   DDD_IFOnewayX(context,
465                 dddctrl.ElementVHIF, IF_FORWARD, sizeof(int),
466                 Gather_VHGhostCmd, Scatter_VHGhostCmd);
467 
468   return(0);
469 }
470 
471 /****************************************************************************/
472 
473 #ifdef __OVERLAP2__
XferNodesForOverlap2(GRID * theGrid)474 static int XferNodesForOverlap2 (GRID *theGrid)
475 {
476   auto& dddctrl = ddd_ctrl(theGrid->dddContext());
477   ELEMENT *theElement;
478   NODE    *theNode;
479   INT i,part;
480   MATRIX  *mat,*mat2;
481   VECTOR  *vec,*dest;
482   INT Size;
483 
484   for(theElement=FIRSTELEMENT(theGrid); theElement!=NULL; theElement=SUCCE(theElement))
485   {
486     /* ensuring the overlap is for all elements necessary, because even for
487        elements remaining on this processor their overlap may have been deleted
488        some lines above */
489 
490     part = PARTITION(theElement);
491 
492     /* traverse all corner vectors */
493     for(i=0; i<CORNERS_OF_ELEM(theElement); i++)
494     {
495       theNode = CORNER(theElement,i);
496       vec = NVECTOR(theNode);
497 
498       PRINTDEBUG(dddif,2,(PFMT " XferGridWithOverlap():  e=" EID_FMTX
499                           " Xfer n=" ID_FMTX " i=%d\n",
500                           me,EID_PRTX(theElement),ID_PRTX(theNode),i))
501 
502       /* for master vectors all matrix neighbors within link depth 2
503           must be copied too; the vec itself is automatically copied
504               by the node-copy-handler */
505       for(mat=MNEXT(VSTART(vec)); mat!=NULL; mat=MNEXT(mat))
506       {
507         dest = MDEST(mat);
508         if (dest != NULL)
509         {
510           Size = sizeof(VECTOR)-sizeof(DOUBLE)
511                  +FMT_S_VEC_TP(MGFORMAT(dddctrl.currMG),VTYPE(dest));
512 
513           PRINTDEBUG(dddif,2,(PFMT " XferGridWithOverlap(): n=" ID_FMTX
514                               " Xfer NODEVEC=" VINDEX_FMTX " 1. NBvec  "
515                               VINDEX_FMTX " size=%d\n",
516                               me,ID_PRTX(theNode),VINDEX_PRTX(vec),VINDEX_PRTX(dest),Size))
517           /* TODO: only vectors are necessary; only for debugging: send also the corresponding node to have geometric information */
518           SETNO_DELETE_OVERLAP2((NODE*)VOBJECT(dest),1);
519           DDD_XferCopyObj(PARHDR((NODE*)VOBJECT(dest)), part, PrioHGhost);
520           /*DDD_XferCopyObjX(PARHDR(dest), part, PrioHGhost, Size);*/
521         }
522 
523         for(mat2=MNEXT(VSTART(dest)); mat2!=NULL; mat2=MNEXT(mat2))
524         {
525           dest = MDEST(mat2);
526           if (dest != NULL)
527           {
528             Size = sizeof(VECTOR)-sizeof(DOUBLE)
529                    +FMT_S_VEC_TP(MGFORMAT(dddctrl.currMG),VTYPE(dest));
530 
531             PRINTDEBUG(dddif,2,(PFMT " XferGridWithOverlap(): n=" ID_FMTX
532                                 " Xfer NODEVEC=" VINDEX_FMTX " 2. NBvec  "
533                                 VINDEX_FMTX " size=%d\n",
534                                 me,ID_PRTX(theNode),VINDEX_PRTX(vec),VINDEX_PRTX(dest),Size))
535 
536             /* TODO: only vectors are necessary; only for debugging: send also the corresponding node to have geometric information */
537             SETNO_DELETE_OVERLAP2((NODE*)VOBJECT(dest),1);
538             DDD_XferCopyObj(PARHDR((NODE*)VOBJECT(dest)), part, PrioHGhost);
539             /*DDD_XferCopyObjX(PARHDR(dest), part, PrioHGhost, Size);*/
540           }
541         }
542       }
543     }
544   }
545   return (0);
546 }
547 #endif
548 
549 /****************************************************************************/
550 /*
551    XferGridWithOverlap - send elements to other procs, keep overlapping region of one element, maintain correct priorities at interfaces.
552 
553    SYNOPSIS:
554    static void XferGridWithOverlap (GRID *theGrid);
555 
556    PARAMETERS:
557    .  theGrid
558 
559    DESCRIPTION:
560    This function sends elements to other procs, keeps overlapping region of one element and maintains correct priorities at interfaces. The destination procs have been computed by the RecursiveCoordinateBisection function and put into the elements' PARTITION-entries.
561 
562    RETURN VALUE:
563    void
564  */
565 /****************************************************************************/
566 
XferGridWithOverlap(GRID * theGrid)567 static int XferGridWithOverlap (GRID *theGrid)
568 {
569   ELEMENT *theElement, *theFather, *theNeighbor;
570   ELEMENT *SonList[MAX_SONS];
571   INT i,j,overlap_elem,part;
572   INT migrated = 0;
573 
574   DDD::DDDContext& context = theGrid->dddContext();
575   const auto& me = context.me();
576 
577   for(theElement=FIRSTELEMENT(theGrid); theElement!=NULL; theElement=SUCCE(theElement))
578   {
579     /* goal processor */
580     part = PARTITION(theElement);
581 
582     /* create Master copy */
583     XferElement(context, theElement, part, PrioMaster);
584 
585                 #ifdef STAT_OUT
586     /* count elems */
587     if (part != me) migrated++;
588                 #endif
589   }
590 
591   /* create grid overlap */
592   for(theElement=FIRSTELEMENT(theGrid); theElement!=NULL; theElement=SUCCE(theElement))
593   {
594     overlap_elem = 0;
595 
596     /* create 1-overlapping of horizontal elements */
597     for(j=0; j<SIDES_OF_ELEM(theElement); j++)
598     {
599       theNeighbor = NBELEM(theElement,j);
600 
601       if (theNeighbor != NULL)
602       {
603         if (PARTITION(theElement)!=PARTITION(theNeighbor))
604         {
605           /* create Ghost copy */
606           XferElement(context, theElement, PARTITION(theNeighbor), PrioHGhost);
607         }
608 
609         /* remember any local neighbour element */
610         if (PARTITION(theNeighbor)==me)
611           overlap_elem = 1;
612       }
613     }
614 
615     /* create 1-overlapping of vertical elements */
616     theFather = EFATHER(theElement);
617     if (theFather != NULL)
618     {
619       if (PARTITION(theFather) != PARTITION(theElement) ||
620           !EMASTER(theFather))
621         /* create VGhost copy */
622         XferElement(context, theFather, PARTITION(theElement), PrioVGhost);
623     }
624     else
625     {
626       ASSERT(LEVEL(theElement) == 0);
627     }
628 
629     /* consider elements on master-proc */
630     if (PARTITION(theElement)!=me)
631     {
632       if (NSONS(theElement) > 0)
633       {
634         if (GetAllSons(theElement,SonList) != 0) assert(0);
635         i = 0;
636         while (SonList[i] != NULL)
637         {
638           if (PARTITION(SonList[i]) == me)
639           {
640             overlap_elem += 2;
641             break;
642           }
643           i++;
644         }
645       }
646 
647       PRINTDEBUG(dddif,1,("%d: XferGridWithOverlap(): elem=" EID_FMTX " p=%d new prio=%d\n",
648                           me,EGID(theElement),PARTITION(theElement),overlap_elem));
649 
650       if (overlap_elem > 0)
651       {
652         /* element is needed, set new prio */
653         switch (overlap_elem)
654         {
655         case (1) :
656           SETEPRIO(context, theElement,PrioHGhost);
657           break;
658 
659         case (2) :
660           SETEPRIO(context, theElement,PrioVGhost);
661           break;
662 
663         case (3) :
664           SETEPRIO(context, theElement,PrioVGhost);
665           break;
666 
667         default :
668           assert(0);
669         }
670       }
671       else
672       {
673         /* element isn't needed */
674         PRINTDEBUG(dddif,2,("%d: XferGridWithOverlap(): XferDel elem=%d to p=%d prio=%d\n",
675                             me,EGID(theElement),PARTITION(theElement),PrioHGhost));
676 
677         XFEREDELETE(context, theElement);
678       }
679     }
680   }
681 
682 #ifdef __OVERLAP2__
683   if (XferNodesForOverlap2(theGrid)) assert(0);
684 #endif
685 
686   return(migrated);
687 }
688 
689 
690 
691 /****************************************************************************/
692 
693 
694 /****************************************************************************/
695 /*
696    InheritPartitionBottomTop -
697 
698    SYNOPSIS:
699    static void InheritPartitionBottomTop (ELEMENT *e);
700 
701    PARAMETERS:
702    .  e
703 
704    DESCRIPTION:
705 
706    RETURN VALUE:
707    void
708  */
709 /****************************************************************************/
710 
InheritPartitionBottomTop(ELEMENT * e)711 static void InheritPartitionBottomTop (ELEMENT *e)
712 {
713   int i;
714   ELEMENT *SonList[MAX_SONS];
715 
716   if (GetSons(e,SonList) != GM_OK) assert(0);
717 
718   for(i=0; i<MAX_SONS; i++)
719   {
720     ELEMENT *son = SonList[i];
721     if (son==NULL) break;
722 
723     PARTITION(son) = PARTITION(e);
724     InheritPartitionBottomTop(son);
725   }
726 }
727 
728 
729 /****************************************************************************/
730 
731 
732 /****************************************************************************/
733 /*
734    TransferGridFromLevel -
735 
736    SYNOPSIS:
737    int TransferGridFromLevel (MULTIGRID *theMG, INT level);
738 
739    PARAMETERS:
740    .  theMG
741    .  level
742 
743    DESCRIPTION:
744 
745    RETURN VALUE:
746    int
747  */
748 /****************************************************************************/
749 
TransferGridFromLevel(MULTIGRID * theMG,INT level)750 int NS_DIM_PREFIX TransferGridFromLevel (MULTIGRID *theMG, INT level)
751 {
752   INT g;
753   INT migrated = 0;       /* number of elements moved */
754 #ifdef STAT_OUT
755   DOUBLE trans_begin, trans_end, cons_end;
756 #endif
757 
758 #ifdef __OVERLAP2__
759   NODE *node;
760 
761   Set_Current_BVP(theMG->theBVP);
762 
763   ASSERT(AllocateControlEntry(NODE_CW,NO_DELETE_OVERLAP2_LEN,&ce_NO_DELETE_OVERLAP2) == GM_OK);
764   for (g=0; g<=TOPLEVEL(theMG); g++)
765   {
766     GRID *theGrid = GRID_ON_LEVEL(theMG,g);
767     for( node=PFIRSTNODE(theGrid); node!= NULL; node=SUCCN(node) )
768       SETNO_DELETE_OVERLAP2(node,0);                    /* reset flag */
769   }
770 #endif
771 
772   if (DisposeBottomHeapTmpMemory(theMG)) REP_ERR_RETURN(1);
773 
774 #ifdef STAT_OUT
775   trans_begin = CURRENT_TIME;
776 #endif
777 
778   /* send new destination to ghost elements */
779   UpdateGhostDests(theMG);
780 
781   /* init transfer */
782   ddd_HandlerInit(theMG->dddContext(), HSET_XFER);
783 
784   /* start physical transfer */
785   DDD_XferBegin(theMG->dddContext());
786 
787   {
788     /* send 'commands' to ghosts in old partitioning */
789     ComputeGhostCmds(theMG);
790 
791     /* send all grids */
792     /*		for (g=TOPLEVEL(theMG); g>=0; g--) */
793     for (g=0; g<=TOPLEVEL(theMG); g++)
794     {
795       GRID *theGrid = GRID_ON_LEVEL(theMG,g);
796       if (NT(theGrid)>0) migrated += XferGridWithOverlap(theGrid);
797     }
798   }
799 
800   DDD_XferEnd(theMG->dddContext());
801 
802 #ifdef STAT_OUT
803   trans_end = CURRENT_TIME;
804 #endif
805 
806 #ifdef __OVERLAP2__
807   for (g=0; g<=TOPLEVEL(theMG); g++)
808   {
809     GRID *theGrid = GRID_ON_LEVEL(theMG,g);
810     for( node=PFIRSTNODE(theGrid); node!= NULL; node=SUCCN(node) )
811       SETNO_DELETE_OVERLAP2(node,0);                    /* reset flag */
812   }
813   FreeControlEntry(ce_NO_DELETE_OVERLAP2);
814   ce_NO_DELETE_OVERLAP2 = -1;           /* don't use further NO_DELETE_OVERLAP2 */
815 #endif
816 
817   /* set priorities of border nodes */
818   /* TODO this is an extra communication. eventually integrate this
819               with grid distribution phase. */
820   ConstructConsistentMultiGrid(theMG);
821 
822     #ifndef __EXCHANGE_CONNECTIONS__
823   MGCreateConnection(theMG);
824         #endif
825 
826   /* the grid has changed at least on one processor, thus reset MGSTATUS on all processors */
827   RESETMGSTATUS(theMG);
828 
829         #ifdef STAT_OUT
830   cons_end = CURRENT_TIME;
831 
832   /* sum up moved elements */
833   migrated = UG_GlobalSumINT(theMG->ppifContext(), migrated);
834 
835   UserWriteF("MIGRATION: migrated=%d t_migrate=%.2f t_cons=%.2f\n",
836              migrated,trans_end-trans_begin,cons_end-trans_end);
837         #endif
838 
839         #ifdef Debug
840   if (0)
841     DDD_ConsCheck(theMG->dddContext());
842         #endif
843 
844   return 0;
845 }
846 
847 
848 /****************************************************************************/
849 /*
850    TransferGrid -
851 
852    SYNOPSIS:
853    int TransferGrid (MULTIGRID *theMG);
854 
855    PARAMETERS:
856    .  theMG
857 
858    DESCRIPTION:
859 
860    RETURN VALUE:
861    int
862  */
863 /****************************************************************************/
864 
TransferGrid(MULTIGRID * theMG)865 int NS_DIM_PREFIX TransferGrid (MULTIGRID *theMG)
866 {
867   return TransferGridFromLevel(theMG,0);
868 }
869 
870 /****************************************************************************/
871 
872 #endif  /* ModelP */
873