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