xref: /petsc/src/dm/impls/plex/plexdistribute.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>    /*I      "petscdmplex.h"   I*/
2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h>   /*I      "petscdmlabel.h"  I*/
370034214SMatthew G. Knepley 
43c1f0c11SLawrence Mitchell /*@C
53c1f0c11SLawrence Mitchell   DMPlexSetAdjacencyUser - Define adjacency in the mesh using a user-provided callback
63c1f0c11SLawrence Mitchell 
73c1f0c11SLawrence Mitchell   Input Parameters:
83c1f0c11SLawrence Mitchell + dm      - The DM object
93c1f0c11SLawrence Mitchell . user    - The user callback, may be NULL (to clear the callback)
103c1f0c11SLawrence Mitchell - ctx     - context for callback evaluation, may be NULL
113c1f0c11SLawrence Mitchell 
123c1f0c11SLawrence Mitchell   Level: advanced
133c1f0c11SLawrence Mitchell 
143c1f0c11SLawrence Mitchell   Notes:
153c1f0c11SLawrence Mitchell      The caller of DMPlexGetAdjacency may need to arrange that a large enough array is available for the adjacency.
163c1f0c11SLawrence Mitchell 
173c1f0c11SLawrence Mitchell      Any setting here overrides other configuration of DMPlex adjacency determination.
183c1f0c11SLawrence Mitchell 
19b0441da4SMatthew G. Knepley .seealso: DMSetAdjacency(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexGetAdjacency(), DMPlexGetAdjacencyUser()
203c1f0c11SLawrence Mitchell @*/
213c1f0c11SLawrence Mitchell PetscErrorCode DMPlexSetAdjacencyUser(DM dm,PetscErrorCode (*user)(DM,PetscInt,PetscInt*,PetscInt[],void*),void *ctx)
223c1f0c11SLawrence Mitchell {
233c1f0c11SLawrence Mitchell   DM_Plex *mesh = (DM_Plex *)dm->data;
243c1f0c11SLawrence Mitchell 
253c1f0c11SLawrence Mitchell   PetscFunctionBegin;
263c1f0c11SLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
273c1f0c11SLawrence Mitchell   mesh->useradjacency = user;
283c1f0c11SLawrence Mitchell   mesh->useradjacencyctx = ctx;
293c1f0c11SLawrence Mitchell   PetscFunctionReturn(0);
303c1f0c11SLawrence Mitchell }
313c1f0c11SLawrence Mitchell 
323c1f0c11SLawrence Mitchell /*@C
333c1f0c11SLawrence Mitchell   DMPlexGetAdjacencyUser - get the user-defined adjacency callback
343c1f0c11SLawrence Mitchell 
353c1f0c11SLawrence Mitchell   Input Parameter:
363c1f0c11SLawrence Mitchell . dm      - The DM object
373c1f0c11SLawrence Mitchell 
383c1f0c11SLawrence Mitchell   Output Parameters:
396b867d5aSJose E. Roman + user    - The user callback
403c1f0c11SLawrence Mitchell - ctx     - context for callback evaluation
413c1f0c11SLawrence Mitchell 
423c1f0c11SLawrence Mitchell   Level: advanced
433c1f0c11SLawrence Mitchell 
44b0441da4SMatthew G. Knepley .seealso: DMSetAdjacency(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexGetAdjacency(), DMPlexSetAdjacencyUser()
453c1f0c11SLawrence Mitchell @*/
463c1f0c11SLawrence Mitchell PetscErrorCode DMPlexGetAdjacencyUser(DM dm, PetscErrorCode (**user)(DM,PetscInt,PetscInt*,PetscInt[],void*), void **ctx)
473c1f0c11SLawrence Mitchell {
483c1f0c11SLawrence Mitchell   DM_Plex *mesh = (DM_Plex *)dm->data;
493c1f0c11SLawrence Mitchell 
503c1f0c11SLawrence Mitchell   PetscFunctionBegin;
513c1f0c11SLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
523c1f0c11SLawrence Mitchell   if (user) *user = mesh->useradjacency;
533c1f0c11SLawrence Mitchell   if (ctx) *ctx = mesh->useradjacencyctx;
543c1f0c11SLawrence Mitchell   PetscFunctionReturn(0);
553c1f0c11SLawrence Mitchell }
563c1f0c11SLawrence Mitchell 
5770034214SMatthew G. Knepley /*@
58a17985deSToby Isaac   DMPlexSetAdjacencyUseAnchors - Define adjacency in the mesh using the point-to-point constraints.
598b0b4c70SToby Isaac 
608b0b4c70SToby Isaac   Input Parameters:
618b0b4c70SToby Isaac + dm      - The DM object
625b317d89SToby Isaac - useAnchors - Flag to use the constraints.  If PETSC_TRUE, then constrained points are omitted from DMPlexGetAdjacency(), and their anchor points appear in their place.
638b0b4c70SToby Isaac 
648b0b4c70SToby Isaac   Level: intermediate
658b0b4c70SToby Isaac 
66b0441da4SMatthew G. Knepley .seealso: DMGetAdjacency(), DMSetAdjacency(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexSetAnchors()
678b0b4c70SToby Isaac @*/
685b317d89SToby Isaac PetscErrorCode DMPlexSetAdjacencyUseAnchors(DM dm, PetscBool useAnchors)
698b0b4c70SToby Isaac {
708b0b4c70SToby Isaac   DM_Plex *mesh = (DM_Plex *) dm->data;
718b0b4c70SToby Isaac 
728b0b4c70SToby Isaac   PetscFunctionBegin;
738b0b4c70SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
745b317d89SToby Isaac   mesh->useAnchors = useAnchors;
758b0b4c70SToby Isaac   PetscFunctionReturn(0);
768b0b4c70SToby Isaac }
778b0b4c70SToby Isaac 
788b0b4c70SToby Isaac /*@
79a17985deSToby Isaac   DMPlexGetAdjacencyUseAnchors - Query whether adjacency in the mesh uses the point-to-point constraints.
808b0b4c70SToby Isaac 
818b0b4c70SToby Isaac   Input Parameter:
828b0b4c70SToby Isaac . dm      - The DM object
838b0b4c70SToby Isaac 
848b0b4c70SToby Isaac   Output Parameter:
855b317d89SToby Isaac . useAnchors - Flag to use the closure.  If PETSC_TRUE, then constrained points are omitted from DMPlexGetAdjacency(), and their anchor points appear in their place.
868b0b4c70SToby Isaac 
878b0b4c70SToby Isaac   Level: intermediate
888b0b4c70SToby Isaac 
89b0441da4SMatthew G. Knepley .seealso: DMPlexSetAdjacencyUseAnchors(), DMSetAdjacency(), DMGetAdjacency(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexSetAnchors()
908b0b4c70SToby Isaac @*/
915b317d89SToby Isaac PetscErrorCode DMPlexGetAdjacencyUseAnchors(DM dm, PetscBool *useAnchors)
928b0b4c70SToby Isaac {
938b0b4c70SToby Isaac   DM_Plex *mesh = (DM_Plex *) dm->data;
948b0b4c70SToby Isaac 
958b0b4c70SToby Isaac   PetscFunctionBegin;
968b0b4c70SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97064a246eSJacob Faibussowitsch   PetscValidBoolPointer(useAnchors, 2);
985b317d89SToby Isaac   *useAnchors = mesh->useAnchors;
998b0b4c70SToby Isaac   PetscFunctionReturn(0);
1008b0b4c70SToby Isaac }
1018b0b4c70SToby Isaac 
10270034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Cone_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[])
10370034214SMatthew G. Knepley {
10470034214SMatthew G. Knepley   const PetscInt *cone = NULL;
10570034214SMatthew G. Knepley   PetscInt        numAdj = 0, maxAdjSize = *adjSize, coneSize, c;
10670034214SMatthew G. Knepley 
10770034214SMatthew G. Knepley   PetscFunctionBeginHot;
1085f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
1095f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCone(dm, p, &cone));
1104b6b44bdSMatthew G. Knepley   for (c = 0; c <= coneSize; ++c) {
1114b6b44bdSMatthew G. Knepley     const PetscInt  point   = !c ? p : cone[c-1];
11270034214SMatthew G. Knepley     const PetscInt *support = NULL;
11370034214SMatthew G. Knepley     PetscInt        supportSize, s, q;
11470034214SMatthew G. Knepley 
1155f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetSupportSize(dm, point, &supportSize));
1165f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetSupport(dm, point, &support));
11770034214SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
118527e7439SSatish Balay       for (q = 0; q < numAdj || ((void)(adj[numAdj++] = support[s]),0); ++q) {
11970034214SMatthew G. Knepley         if (support[s] == adj[q]) break;
12070034214SMatthew G. Knepley       }
1212c71b3e2SJacob Faibussowitsch       PetscCheckFalse(numAdj > maxAdjSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
12270034214SMatthew G. Knepley     }
12370034214SMatthew G. Knepley   }
12470034214SMatthew G. Knepley   *adjSize = numAdj;
12570034214SMatthew G. Knepley   PetscFunctionReturn(0);
12670034214SMatthew G. Knepley }
12770034214SMatthew G. Knepley 
12870034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Support_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[])
12970034214SMatthew G. Knepley {
13070034214SMatthew G. Knepley   const PetscInt *support = NULL;
13170034214SMatthew G. Knepley   PetscInt        numAdj   = 0, maxAdjSize = *adjSize, supportSize, s;
13270034214SMatthew G. Knepley 
13370034214SMatthew G. Knepley   PetscFunctionBeginHot;
1345f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetSupportSize(dm, p, &supportSize));
1355f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetSupport(dm, p, &support));
1364b6b44bdSMatthew G. Knepley   for (s = 0; s <= supportSize; ++s) {
1374b6b44bdSMatthew G. Knepley     const PetscInt  point = !s ? p : support[s-1];
13870034214SMatthew G. Knepley     const PetscInt *cone  = NULL;
13970034214SMatthew G. Knepley     PetscInt        coneSize, c, q;
14070034214SMatthew G. Knepley 
1415f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeSize(dm, point, &coneSize));
1425f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dm, point, &cone));
14370034214SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
144527e7439SSatish Balay       for (q = 0; q < numAdj || ((void)(adj[numAdj++] = cone[c]),0); ++q) {
14570034214SMatthew G. Knepley         if (cone[c] == adj[q]) break;
14670034214SMatthew G. Knepley       }
1472c71b3e2SJacob Faibussowitsch       PetscCheckFalse(numAdj > maxAdjSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
14870034214SMatthew G. Knepley     }
14970034214SMatthew G. Knepley   }
15070034214SMatthew G. Knepley   *adjSize = numAdj;
15170034214SMatthew G. Knepley   PetscFunctionReturn(0);
15270034214SMatthew G. Knepley }
15370034214SMatthew G. Knepley 
15470034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Transitive_Internal(DM dm, PetscInt p, PetscBool useClosure, PetscInt *adjSize, PetscInt adj[])
15570034214SMatthew G. Knepley {
15670034214SMatthew G. Knepley   PetscInt      *star = NULL;
15770034214SMatthew G. Knepley   PetscInt       numAdj = 0, maxAdjSize = *adjSize, starSize, s;
15870034214SMatthew G. Knepley 
15970034214SMatthew G. Knepley   PetscFunctionBeginHot;
1605f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, &star));
16170034214SMatthew G. Knepley   for (s = 0; s < starSize*2; s += 2) {
16270034214SMatthew G. Knepley     const PetscInt *closure = NULL;
16370034214SMatthew G. Knepley     PetscInt        closureSize, c, q;
16470034214SMatthew G. Knepley 
1655f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure));
16670034214SMatthew G. Knepley     for (c = 0; c < closureSize*2; c += 2) {
167527e7439SSatish Balay       for (q = 0; q < numAdj || ((void)(adj[numAdj++] = closure[c]),0); ++q) {
16870034214SMatthew G. Knepley         if (closure[c] == adj[q]) break;
16970034214SMatthew G. Knepley       }
1702c71b3e2SJacob Faibussowitsch       PetscCheckFalse(numAdj > maxAdjSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
17170034214SMatthew G. Knepley     }
1725f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure));
17370034214SMatthew G. Knepley   }
1745f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexRestoreTransitiveClosure(dm, p, useClosure, &starSize, &star));
17570034214SMatthew G. Knepley   *adjSize = numAdj;
17670034214SMatthew G. Knepley   PetscFunctionReturn(0);
17770034214SMatthew G. Knepley }
17870034214SMatthew G. Knepley 
1795b317d89SToby Isaac PetscErrorCode DMPlexGetAdjacency_Internal(DM dm, PetscInt p, PetscBool useCone, PetscBool useTransitiveClosure, PetscBool useAnchors, PetscInt *adjSize, PetscInt *adj[])
18070034214SMatthew G. Knepley {
18179bad331SMatthew G. Knepley   static PetscInt asiz = 0;
1828b0b4c70SToby Isaac   PetscInt maxAnchors = 1;
1838b0b4c70SToby Isaac   PetscInt aStart = -1, aEnd = -1;
1848b0b4c70SToby Isaac   PetscInt maxAdjSize;
1858b0b4c70SToby Isaac   PetscSection aSec = NULL;
1868b0b4c70SToby Isaac   IS aIS = NULL;
1878b0b4c70SToby Isaac   const PetscInt *anchors;
1883c1f0c11SLawrence Mitchell   DM_Plex *mesh = (DM_Plex *)dm->data;
18970034214SMatthew G. Knepley 
19070034214SMatthew G. Knepley   PetscFunctionBeginHot;
1915b317d89SToby Isaac   if (useAnchors) {
1925f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetAnchors(dm,&aSec,&aIS));
1938b0b4c70SToby Isaac     if (aSec) {
1945f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetMaxDof(aSec,&maxAnchors));
19524c766afSToby Isaac       maxAnchors = PetscMax(1,maxAnchors);
1965f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetChart(aSec,&aStart,&aEnd));
1975f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(aIS,&anchors));
1988b0b4c70SToby Isaac     }
1998b0b4c70SToby Isaac   }
20079bad331SMatthew G. Knepley   if (!*adj) {
20124c766afSToby Isaac     PetscInt depth, coneSeries, supportSeries, maxC, maxS, pStart, pEnd;
20279bad331SMatthew G. Knepley 
2035f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetChart(dm, &pStart,&pEnd));
2045f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepth(dm, &depth));
205412e9a14SMatthew G. Knepley     depth = PetscMax(depth, -depth);
2065f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetMaxSizes(dm, &maxC, &maxS));
20724c766afSToby Isaac     coneSeries    = (maxC > 1) ? ((PetscPowInt(maxC,depth+1)-1)/(maxC-1)) : depth+1;
20824c766afSToby Isaac     supportSeries = (maxS > 1) ? ((PetscPowInt(maxS,depth+1)-1)/(maxS-1)) : depth+1;
20924c766afSToby Isaac     asiz  = PetscMax(PetscPowInt(maxS,depth)*coneSeries,PetscPowInt(maxC,depth)*supportSeries);
2108b0b4c70SToby Isaac     asiz *= maxAnchors;
21124c766afSToby Isaac     asiz  = PetscMin(asiz,pEnd-pStart);
2125f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(asiz,adj));
21379bad331SMatthew G. Knepley   }
21479bad331SMatthew G. Knepley   if (*adjSize < 0) *adjSize = asiz;
2158b0b4c70SToby Isaac   maxAdjSize = *adjSize;
2163c1f0c11SLawrence Mitchell   if (mesh->useradjacency) {
2175f80ce2aSJacob Faibussowitsch     CHKERRQ((*mesh->useradjacency)(dm, p, adjSize, *adj, mesh->useradjacencyctx));
2183c1f0c11SLawrence Mitchell   } else if (useTransitiveClosure) {
2195f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetAdjacency_Transitive_Internal(dm, p, useCone, adjSize, *adj));
22070034214SMatthew G. Knepley   } else if (useCone) {
2215f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetAdjacency_Cone_Internal(dm, p, adjSize, *adj));
22270034214SMatthew G. Knepley   } else {
2235f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetAdjacency_Support_Internal(dm, p, adjSize, *adj));
22470034214SMatthew G. Knepley   }
2255b317d89SToby Isaac   if (useAnchors && aSec) {
2268b0b4c70SToby Isaac     PetscInt origSize = *adjSize;
2278b0b4c70SToby Isaac     PetscInt numAdj = origSize;
2288b0b4c70SToby Isaac     PetscInt i = 0, j;
2298b0b4c70SToby Isaac     PetscInt *orig = *adj;
2308b0b4c70SToby Isaac 
2318b0b4c70SToby Isaac     while (i < origSize) {
2328b0b4c70SToby Isaac       PetscInt p = orig[i];
2338b0b4c70SToby Isaac       PetscInt aDof = 0;
2348b0b4c70SToby Isaac 
2358b0b4c70SToby Isaac       if (p >= aStart && p < aEnd) {
2365f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(aSec,p,&aDof));
2378b0b4c70SToby Isaac       }
2388b0b4c70SToby Isaac       if (aDof) {
2398b0b4c70SToby Isaac         PetscInt aOff;
2408b0b4c70SToby Isaac         PetscInt s, q;
2418b0b4c70SToby Isaac 
2428b0b4c70SToby Isaac         for (j = i + 1; j < numAdj; j++) {
2438b0b4c70SToby Isaac           orig[j - 1] = orig[j];
2448b0b4c70SToby Isaac         }
2458b0b4c70SToby Isaac         origSize--;
2468b0b4c70SToby Isaac         numAdj--;
2475f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(aSec,p,&aOff));
2488b0b4c70SToby Isaac         for (s = 0; s < aDof; ++s) {
249527e7439SSatish Balay           for (q = 0; q < numAdj || ((void)(orig[numAdj++] = anchors[aOff+s]),0); ++q) {
2508b0b4c70SToby Isaac             if (anchors[aOff+s] == orig[q]) break;
2518b0b4c70SToby Isaac           }
2522c71b3e2SJacob Faibussowitsch           PetscCheckFalse(numAdj > maxAdjSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
2538b0b4c70SToby Isaac         }
2548b0b4c70SToby Isaac       }
2558b0b4c70SToby Isaac       else {
2568b0b4c70SToby Isaac         i++;
2578b0b4c70SToby Isaac       }
2588b0b4c70SToby Isaac     }
2598b0b4c70SToby Isaac     *adjSize = numAdj;
2605f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(aIS,&anchors));
2618b0b4c70SToby Isaac   }
26270034214SMatthew G. Knepley   PetscFunctionReturn(0);
26370034214SMatthew G. Knepley }
26470034214SMatthew G. Knepley 
26570034214SMatthew G. Knepley /*@
26670034214SMatthew G. Knepley   DMPlexGetAdjacency - Return all points adjacent to the given point
26770034214SMatthew G. Knepley 
26870034214SMatthew G. Knepley   Input Parameters:
26970034214SMatthew G. Knepley + dm - The DM object
2706b867d5aSJose E. Roman - p  - The point
27170034214SMatthew G. Knepley 
2726b867d5aSJose E. Roman   Input/Output Parameters:
2736b867d5aSJose E. Roman + adjSize - The maximum size of adj if it is non-NULL, or PETSC_DETERMINE;
2746b867d5aSJose E. Roman             on output the number of adjacent points
2756b867d5aSJose E. Roman - adj - Either NULL so that the array is allocated, or an existing array with size adjSize;
2766b867d5aSJose E. Roman         on output contains the adjacent points
27770034214SMatthew G. Knepley 
27870034214SMatthew G. Knepley   Level: advanced
27970034214SMatthew G. Knepley 
28095452b02SPatrick Sanan   Notes:
28195452b02SPatrick Sanan     The user must PetscFree the adj array if it was not passed in.
28270034214SMatthew G. Knepley 
283b0441da4SMatthew G. Knepley .seealso: DMSetAdjacency(), DMPlexDistribute(), DMCreateMatrix(), DMPlexPreallocateOperator()
28470034214SMatthew G. Knepley @*/
28570034214SMatthew G. Knepley PetscErrorCode DMPlexGetAdjacency(DM dm, PetscInt p, PetscInt *adjSize, PetscInt *adj[])
28670034214SMatthew G. Knepley {
2871cf84007SMatthew G. Knepley   PetscBool      useCone, useClosure, useAnchors;
28870034214SMatthew G. Knepley 
28970034214SMatthew G. Knepley   PetscFunctionBeginHot;
29070034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29170034214SMatthew G. Knepley   PetscValidPointer(adjSize,3);
29270034214SMatthew G. Knepley   PetscValidPointer(adj,4);
2935f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetBasicAdjacency(dm, &useCone, &useClosure));
2945f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors));
2955f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, adjSize, adj));
29670034214SMatthew G. Knepley   PetscFunctionReturn(0);
29770034214SMatthew G. Knepley }
29808633170SToby Isaac 
299b0a623aaSMatthew G. Knepley /*@
300b0a623aaSMatthew G. Knepley   DMPlexCreateTwoSidedProcessSF - Create an SF which just has process connectivity
301b0a623aaSMatthew G. Knepley 
302d083f849SBarry Smith   Collective on dm
303b0a623aaSMatthew G. Knepley 
304b0a623aaSMatthew G. Knepley   Input Parameters:
305b0a623aaSMatthew G. Knepley + dm      - The DM
3066b867d5aSJose E. Roman . sfPoint - The PetscSF which encodes point connectivity
3076b867d5aSJose E. Roman . rootRankSection -
3086b867d5aSJose E. Roman . rootRanks -
3096b867d5aSJose E. Roman . leftRankSection -
3106b867d5aSJose E. Roman - leafRanks -
311b0a623aaSMatthew G. Knepley 
312b0a623aaSMatthew G. Knepley   Output Parameters:
313b0a623aaSMatthew G. Knepley + processRanks - A list of process neighbors, or NULL
314b0a623aaSMatthew G. Knepley - sfProcess    - An SF encoding the two-sided process connectivity, or NULL
315b0a623aaSMatthew G. Knepley 
316b0a623aaSMatthew G. Knepley   Level: developer
317b0a623aaSMatthew G. Knepley 
318b0a623aaSMatthew G. Knepley .seealso: PetscSFCreate(), DMPlexCreateProcessSF()
319b0a623aaSMatthew G. Knepley @*/
320b0a623aaSMatthew G. Knepley PetscErrorCode DMPlexCreateTwoSidedProcessSF(DM dm, PetscSF sfPoint, PetscSection rootRankSection, IS rootRanks, PetscSection leafRankSection, IS leafRanks, IS *processRanks, PetscSF *sfProcess)
321b0a623aaSMatthew G. Knepley {
322b0a623aaSMatthew G. Knepley   const PetscSFNode *remotePoints;
323b0a623aaSMatthew G. Knepley   PetscInt          *localPointsNew;
324b0a623aaSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
325b0a623aaSMatthew G. Knepley   const PetscInt    *nranks;
326b0a623aaSMatthew G. Knepley   PetscInt          *ranksNew;
327b0a623aaSMatthew G. Knepley   PetscBT            neighbors;
328b0a623aaSMatthew G. Knepley   PetscInt           pStart, pEnd, p, numLeaves, l, numNeighbors, n;
3299852e123SBarry Smith   PetscMPIInt        size, proc, rank;
330b0a623aaSMatthew G. Knepley 
331b0a623aaSMatthew G. Knepley   PetscFunctionBegin;
332b0a623aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
333b0a623aaSMatthew G. Knepley   PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2);
334064a246eSJacob Faibussowitsch   if (processRanks) {PetscValidPointer(processRanks, 7);}
335064a246eSJacob Faibussowitsch   if (sfProcess)    {PetscValidPointer(sfProcess, 8);}
3365f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size));
3375f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
3385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(sfPoint, NULL, &numLeaves, NULL, &remotePoints));
3395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscBTCreate(size, &neighbors));
3405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscBTMemzero(size, neighbors));
341b0a623aaSMatthew G. Knepley   /* Compute root-to-leaf process connectivity */
3425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(rootRankSection, &pStart, &pEnd));
3435f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(rootRanks, &nranks));
344b0a623aaSMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
345b0a623aaSMatthew G. Knepley     PetscInt ndof, noff, n;
346b0a623aaSMatthew G. Knepley 
3475f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(rootRankSection, p, &ndof));
3485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(rootRankSection, p, &noff));
3495f80ce2aSJacob Faibussowitsch     for (n = 0; n < ndof; ++n) CHKERRQ(PetscBTSet(neighbors, nranks[noff+n]));
350b0a623aaSMatthew G. Knepley   }
3515f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(rootRanks, &nranks));
352b0a623aaSMatthew G. Knepley   /* Compute leaf-to-neighbor process connectivity */
3535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(leafRankSection, &pStart, &pEnd));
3545f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(leafRanks, &nranks));
355b0a623aaSMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
356b0a623aaSMatthew G. Knepley     PetscInt ndof, noff, n;
357b0a623aaSMatthew G. Knepley 
3585f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(leafRankSection, p, &ndof));
3595f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(leafRankSection, p, &noff));
3605f80ce2aSJacob Faibussowitsch     for (n = 0; n < ndof; ++n) CHKERRQ(PetscBTSet(neighbors, nranks[noff+n]));
361b0a623aaSMatthew G. Knepley   }
3625f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(leafRanks, &nranks));
363b0a623aaSMatthew G. Knepley   /* Compute leaf-to-root process connectivity */
364b0a623aaSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {PetscBTSet(neighbors, remotePoints[l].rank);}
365b0a623aaSMatthew G. Knepley   /* Calculate edges */
366b0a623aaSMatthew G. Knepley   PetscBTClear(neighbors, rank);
3679852e123SBarry Smith   for (proc = 0, numNeighbors = 0; proc < size; ++proc) {if (PetscBTLookup(neighbors, proc)) ++numNeighbors;}
3685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(numNeighbors, &ranksNew));
3695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(numNeighbors, &localPointsNew));
3705f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(numNeighbors, &remotePointsNew));
3719852e123SBarry Smith   for (proc = 0, n = 0; proc < size; ++proc) {
372b0a623aaSMatthew G. Knepley     if (PetscBTLookup(neighbors, proc)) {
373b0a623aaSMatthew G. Knepley       ranksNew[n]              = proc;
374b0a623aaSMatthew G. Knepley       localPointsNew[n]        = proc;
375b0a623aaSMatthew G. Knepley       remotePointsNew[n].index = rank;
376b0a623aaSMatthew G. Knepley       remotePointsNew[n].rank  = proc;
377b0a623aaSMatthew G. Knepley       ++n;
378b0a623aaSMatthew G. Knepley     }
379b0a623aaSMatthew G. Knepley   }
3805f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscBTDestroy(&neighbors));
3815f80ce2aSJacob Faibussowitsch   if (processRanks) CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)dm), numNeighbors, ranksNew, PETSC_OWN_POINTER, processRanks));
3825f80ce2aSJacob Faibussowitsch   else              CHKERRQ(PetscFree(ranksNew));
383b0a623aaSMatthew G. Knepley   if (sfProcess) {
3845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess));
3855f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject) *sfProcess, "Two-Sided Process SF"));
3865f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFSetFromOptions(*sfProcess));
3875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFSetGraph(*sfProcess, size, numNeighbors, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER));
388b0a623aaSMatthew G. Knepley   }
389b0a623aaSMatthew G. Knepley   PetscFunctionReturn(0);
390b0a623aaSMatthew G. Knepley }
391b0a623aaSMatthew G. Knepley 
392b0a623aaSMatthew G. Knepley /*@
393b0a623aaSMatthew G. Knepley   DMPlexDistributeOwnership - Compute owner information for shared points. This basically gets two-sided for an SF.
394b0a623aaSMatthew G. Knepley 
395d083f849SBarry Smith   Collective on dm
396b0a623aaSMatthew G. Knepley 
397b0a623aaSMatthew G. Knepley   Input Parameter:
398b0a623aaSMatthew G. Knepley . dm - The DM
399b0a623aaSMatthew G. Knepley 
400b0a623aaSMatthew G. Knepley   Output Parameters:
401b0a623aaSMatthew G. Knepley + rootSection - The number of leaves for a given root point
402b0a623aaSMatthew G. Knepley . rootrank    - The rank of each edge into the root point
403b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point
404b0a623aaSMatthew G. Knepley - leafrank    - The rank of each process sharing a leaf point
405b0a623aaSMatthew G. Knepley 
406b0a623aaSMatthew G. Knepley   Level: developer
407b0a623aaSMatthew G. Knepley 
408dccdeccaSVaclav Hapla .seealso: DMPlexCreateOverlapLabel(), DMPlexDistribute(), DMPlexDistributeOverlap()
409b0a623aaSMatthew G. Knepley @*/
410b0a623aaSMatthew G. Knepley PetscErrorCode DMPlexDistributeOwnership(DM dm, PetscSection rootSection, IS *rootrank, PetscSection leafSection, IS *leafrank)
411b0a623aaSMatthew G. Knepley {
412b0a623aaSMatthew G. Knepley   MPI_Comm        comm;
413b0a623aaSMatthew G. Knepley   PetscSF         sfPoint;
414b0a623aaSMatthew G. Knepley   const PetscInt *rootdegree;
415b0a623aaSMatthew G. Knepley   PetscInt       *myrank, *remoterank;
416b0a623aaSMatthew G. Knepley   PetscInt        pStart, pEnd, p, nedges;
417b0a623aaSMatthew G. Knepley   PetscMPIInt     rank;
418b0a623aaSMatthew G. Knepley 
419b0a623aaSMatthew G. Knepley   PetscFunctionBegin;
4205f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm));
4215f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
4225f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
4235f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(dm, &sfPoint));
424b0a623aaSMatthew G. Knepley   /* Compute number of leaves for each root */
4255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) rootSection, "Root Section"));
4265f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(rootSection, pStart, pEnd));
4275f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFComputeDegreeBegin(sfPoint, &rootdegree));
4285f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFComputeDegreeEnd(sfPoint, &rootdegree));
4295f80ce2aSJacob Faibussowitsch   for (p = pStart; p < pEnd; ++p) CHKERRQ(PetscSectionSetDof(rootSection, p, rootdegree[p-pStart]));
4305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(rootSection));
431b0a623aaSMatthew G. Knepley   /* Gather rank of each leaf to root */
4325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(rootSection, &nedges));
4335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(pEnd-pStart, &myrank));
4345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nedges,  &remoterank));
435b0a623aaSMatthew G. Knepley   for (p = 0; p < pEnd-pStart; ++p) myrank[p] = rank;
4365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGatherBegin(sfPoint, MPIU_INT, myrank, remoterank));
4375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGatherEnd(sfPoint, MPIU_INT, myrank, remoterank));
4385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(myrank));
4395f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(comm, nedges, remoterank, PETSC_OWN_POINTER, rootrank));
440b0a623aaSMatthew G. Knepley   /* Distribute remote ranks to leaves */
4415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) leafSection, "Leaf Section"));
4425f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexDistributeFieldIS(dm, sfPoint, rootSection, *rootrank, leafSection, leafrank));
443b0a623aaSMatthew G. Knepley   PetscFunctionReturn(0);
444b0a623aaSMatthew G. Knepley }
445b0a623aaSMatthew G. Knepley 
446278397a0SMatthew G. Knepley /*@C
447dccdeccaSVaclav Hapla   DMPlexCreateOverlapLabel - Compute owner information for shared points. This basically gets two-sided for an SF.
448b0a623aaSMatthew G. Knepley 
449d083f849SBarry Smith   Collective on dm
450b0a623aaSMatthew G. Knepley 
451b0a623aaSMatthew G. Knepley   Input Parameters:
452b0a623aaSMatthew G. Knepley + dm          - The DM
45324d039d7SMichael Lange . levels      - Number of overlap levels
454b0a623aaSMatthew G. Knepley . rootSection - The number of leaves for a given root point
455b0a623aaSMatthew G. Knepley . rootrank    - The rank of each edge into the root point
456b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point
457b0a623aaSMatthew G. Knepley - leafrank    - The rank of each process sharing a leaf point
458b0a623aaSMatthew G. Knepley 
459064ec1f3Sprj-   Output Parameter:
460b4ec6ac8SBarry Smith . ovLabel     - DMLabel containing remote overlap contributions as point/rank pairings
461b0a623aaSMatthew G. Knepley 
462b0a623aaSMatthew G. Knepley   Level: developer
463b0a623aaSMatthew G. Knepley 
4641fd9873aSMichael Lange .seealso: DMPlexDistributeOwnership(), DMPlexDistribute()
465b0a623aaSMatthew G. Knepley @*/
466dccdeccaSVaclav Hapla PetscErrorCode DMPlexCreateOverlapLabel(DM dm, PetscInt levels, PetscSection rootSection, IS rootrank, PetscSection leafSection, IS leafrank, DMLabel *ovLabel)
467b0a623aaSMatthew G. Knepley {
468e540f424SMichael Lange   MPI_Comm           comm;
469b0a623aaSMatthew G. Knepley   DMLabel            ovAdjByRank; /* A DMLabel containing all points adjacent to shared points, separated by rank (value in label) */
470874ddda9SLisandro Dalcin   PetscSF            sfPoint;
471b0a623aaSMatthew G. Knepley   const PetscSFNode *remote;
472b0a623aaSMatthew G. Knepley   const PetscInt    *local;
4731fd9873aSMichael Lange   const PetscInt    *nrank, *rrank;
474b0a623aaSMatthew G. Knepley   PetscInt          *adj = NULL;
4751fd9873aSMichael Lange   PetscInt           pStart, pEnd, p, sStart, sEnd, nleaves, l;
4769852e123SBarry Smith   PetscMPIInt        rank, size;
47731bc6364SLisandro Dalcin   PetscBool          flg;
478b0a623aaSMatthew G. Knepley 
479b0a623aaSMatthew G. Knepley   PetscFunctionBegin;
4806ba1a4c7SVaclav Hapla   *ovLabel = NULL;
4815f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm));
4825f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
4835f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
4846ba1a4c7SVaclav Hapla   if (size == 1) PetscFunctionReturn(0);
4855f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(dm, &sfPoint));
4865f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
487d1674c6dSMatthew Knepley   if (!levels) {
488d1674c6dSMatthew Knepley     /* Add owned points */
4895f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel));
4905f80ce2aSJacob Faibussowitsch     for (p = pStart; p < pEnd; ++p) CHKERRQ(DMLabelSetValue(*ovLabel, p, rank));
491d1674c6dSMatthew Knepley     PetscFunctionReturn(0);
492d1674c6dSMatthew Knepley   }
4935f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(leafSection, &sStart, &sEnd));
4945f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote));
4955f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelCreate(PETSC_COMM_SELF, "Overlap adjacency", &ovAdjByRank));
496b0a623aaSMatthew G. Knepley   /* Handle leaves: shared with the root point */
497b0a623aaSMatthew G. Knepley   for (l = 0; l < nleaves; ++l) {
498b0a623aaSMatthew G. Knepley     PetscInt adjSize = PETSC_DETERMINE, a;
499b0a623aaSMatthew G. Knepley 
5005f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetAdjacency(dm, local ? local[l] : l, &adjSize, &adj));
5015f80ce2aSJacob Faibussowitsch     for (a = 0; a < adjSize; ++a) CHKERRQ(DMLabelSetValue(ovAdjByRank, adj[a], remote[l].rank));
502b0a623aaSMatthew G. Knepley   }
5035f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(rootrank, &rrank));
5045f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(leafrank, &nrank));
505b0a623aaSMatthew G. Knepley   /* Handle roots */
506b0a623aaSMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
507b0a623aaSMatthew G. Knepley     PetscInt adjSize = PETSC_DETERMINE, neighbors = 0, noff, n, a;
508b0a623aaSMatthew G. Knepley 
509b0a623aaSMatthew G. Knepley     if ((p >= sStart) && (p < sEnd)) {
510b0a623aaSMatthew G. Knepley       /* Some leaves share a root with other leaves on different processes */
5115f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(leafSection, p, &neighbors));
512b0a623aaSMatthew G. Knepley       if (neighbors) {
5135f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(leafSection, p, &noff));
5145f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetAdjacency(dm, p, &adjSize, &adj));
515b0a623aaSMatthew G. Knepley         for (n = 0; n < neighbors; ++n) {
516b0a623aaSMatthew G. Knepley           const PetscInt remoteRank = nrank[noff+n];
517b0a623aaSMatthew G. Knepley 
518b0a623aaSMatthew G. Knepley           if (remoteRank == rank) continue;
5195f80ce2aSJacob Faibussowitsch           for (a = 0; a < adjSize; ++a) CHKERRQ(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank));
520b0a623aaSMatthew G. Knepley         }
521b0a623aaSMatthew G. Knepley       }
522b0a623aaSMatthew G. Knepley     }
523b0a623aaSMatthew G. Knepley     /* Roots are shared with leaves */
5245f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(rootSection, p, &neighbors));
525b0a623aaSMatthew G. Knepley     if (!neighbors) continue;
5265f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(rootSection, p, &noff));
5275f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetAdjacency(dm, p, &adjSize, &adj));
528b0a623aaSMatthew G. Knepley     for (n = 0; n < neighbors; ++n) {
529b0a623aaSMatthew G. Knepley       const PetscInt remoteRank = rrank[noff+n];
530b0a623aaSMatthew G. Knepley 
531b0a623aaSMatthew G. Knepley       if (remoteRank == rank) continue;
5325f80ce2aSJacob Faibussowitsch       for (a = 0; a < adjSize; ++a) CHKERRQ(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank));
533b0a623aaSMatthew G. Knepley     }
534b0a623aaSMatthew G. Knepley   }
5355f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(adj));
5365f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(rootrank, &rrank));
5375f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(leafrank, &nrank));
53824d039d7SMichael Lange   /* Add additional overlap levels */
539be200f8dSMichael Lange   for (l = 1; l < levels; l++) {
540be200f8dSMichael Lange     /* Propagate point donations over SF to capture remote connections */
5415f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexPartitionLabelPropagate(dm, ovAdjByRank));
542be200f8dSMichael Lange     /* Add next level of point donations to the label */
5435f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexPartitionLabelAdjacency(dm, ovAdjByRank));
544be200f8dSMichael Lange   }
54526a7d390SMatthew G. Knepley   /* We require the closure in the overlap */
5465f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexPartitionLabelClosure(dm, ovAdjByRank));
5475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-overlap_view", &flg));
548e540f424SMichael Lange   if (flg) {
549825f8a23SLisandro Dalcin     PetscViewer viewer;
5505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &viewer));
5515f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelView(ovAdjByRank, viewer));
552b0a623aaSMatthew G. Knepley   }
553874ddda9SLisandro Dalcin   /* Invert sender to receiver label */
5545f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel));
5555f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexPartitionLabelInvert(dm, ovAdjByRank, NULL, *ovLabel));
556a9f1d5b2SMichael Lange   /* Add owned points, except for shared local points */
5575f80ce2aSJacob Faibussowitsch   for (p = pStart; p < pEnd; ++p) CHKERRQ(DMLabelSetValue(*ovLabel, p, rank));
558e540f424SMichael Lange   for (l = 0; l < nleaves; ++l) {
5595f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelClearValue(*ovLabel, local[l], rank));
5605f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelSetValue(*ovLabel, remote[l].index, remote[l].rank));
561e540f424SMichael Lange   }
562e540f424SMichael Lange   /* Clean up */
5635f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelDestroy(&ovAdjByRank));
564b0a623aaSMatthew G. Knepley   PetscFunctionReturn(0);
565b0a623aaSMatthew G. Knepley }
56670034214SMatthew G. Knepley 
56724cc2ca5SMatthew G. Knepley /*@C
56824cc2ca5SMatthew G. Knepley   DMPlexCreateOverlapMigrationSF - Create an SF describing the new mesh distribution to make the overlap described by the input SF
56924cc2ca5SMatthew G. Knepley 
570d083f849SBarry Smith   Collective on dm
57124cc2ca5SMatthew G. Knepley 
57224cc2ca5SMatthew G. Knepley   Input Parameters:
57324cc2ca5SMatthew G. Knepley + dm          - The DM
57424cc2ca5SMatthew G. Knepley - overlapSF   - The SF mapping ghost points in overlap to owner points on other processes
57524cc2ca5SMatthew G. Knepley 
576064ec1f3Sprj-   Output Parameter:
577a2b725a8SWilliam Gropp . migrationSF - An SF that maps original points in old locations to points in new locations
57824cc2ca5SMatthew G. Knepley 
57924cc2ca5SMatthew G. Knepley   Level: developer
58024cc2ca5SMatthew G. Knepley 
581dccdeccaSVaclav Hapla .seealso: DMPlexCreateOverlapLabel(), DMPlexDistributeOverlap(), DMPlexDistribute()
58224cc2ca5SMatthew G. Knepley @*/
58346f9b1c3SMichael Lange PetscErrorCode DMPlexCreateOverlapMigrationSF(DM dm, PetscSF overlapSF, PetscSF *migrationSF)
58446f9b1c3SMichael Lange {
58546f9b1c3SMichael Lange   MPI_Comm           comm;
5869852e123SBarry Smith   PetscMPIInt        rank, size;
58746f9b1c3SMichael Lange   PetscInt           d, dim, p, pStart, pEnd, nroots, nleaves, newLeaves, point, numSharedPoints;
58846f9b1c3SMichael Lange   PetscInt          *pointDepths, *remoteDepths, *ilocal;
58946f9b1c3SMichael Lange   PetscInt          *depthRecv, *depthShift, *depthIdx;
59046f9b1c3SMichael Lange   PetscSFNode       *iremote;
59146f9b1c3SMichael Lange   PetscSF            pointSF;
59246f9b1c3SMichael Lange   const PetscInt    *sharedLocal;
59346f9b1c3SMichael Lange   const PetscSFNode *overlapRemote, *sharedRemote;
59446f9b1c3SMichael Lange 
59546f9b1c3SMichael Lange   PetscFunctionBegin;
59646f9b1c3SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm));
5985f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
5995f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
6005f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
60146f9b1c3SMichael Lange 
60246f9b1c3SMichael Lange   /* Before building the migration SF we need to know the new stratum offsets */
6035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(overlapSF, &nroots, &nleaves, NULL, &overlapRemote));
6045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths));
60546f9b1c3SMichael Lange   for (d=0; d<dim+1; d++) {
6065f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
60746f9b1c3SMichael Lange     for (p=pStart; p<pEnd; p++) pointDepths[p] = d;
60846f9b1c3SMichael Lange   }
60946f9b1c3SMichael Lange   for (p=0; p<nleaves; p++) remoteDepths[p] = -1;
6105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(overlapSF, MPIU_INT, pointDepths, remoteDepths,MPI_REPLACE));
6115f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(overlapSF, MPIU_INT, pointDepths, remoteDepths,MPI_REPLACE));
61246f9b1c3SMichael Lange 
6132d4ee042Sprj-   /* Count received points in each stratum and compute the internal strata shift */
6145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc3(dim+1, &depthRecv, dim+1, &depthShift, dim+1, &depthIdx));
61546f9b1c3SMichael Lange   for (d=0; d<dim+1; d++) depthRecv[d]=0;
61646f9b1c3SMichael Lange   for (p=0; p<nleaves; p++) depthRecv[remoteDepths[p]]++;
61746f9b1c3SMichael Lange   depthShift[dim] = 0;
61846f9b1c3SMichael Lange   for (d=0; d<dim; d++) depthShift[d] = depthRecv[dim];
61946f9b1c3SMichael Lange   for (d=1; d<dim; d++) depthShift[d] += depthRecv[0];
62046f9b1c3SMichael Lange   for (d=dim-2; d>0; d--) depthShift[d] += depthRecv[d+1];
62146f9b1c3SMichael Lange   for (d=0; d<dim+1; d++) {
6225f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
62346f9b1c3SMichael Lange     depthIdx[d] = pStart + depthShift[d];
62446f9b1c3SMichael Lange   }
62546f9b1c3SMichael Lange 
62646f9b1c3SMichael Lange   /* Form the overlap SF build an SF that describes the full overlap migration SF */
6275f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
62846f9b1c3SMichael Lange   newLeaves = pEnd - pStart + nleaves;
6295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(newLeaves, &ilocal));
6305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(newLeaves, &iremote));
63146f9b1c3SMichael Lange   /* First map local points to themselves */
63246f9b1c3SMichael Lange   for (d=0; d<dim+1; d++) {
6335f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
63446f9b1c3SMichael Lange     for (p=pStart; p<pEnd; p++) {
63546f9b1c3SMichael Lange       point = p + depthShift[d];
63646f9b1c3SMichael Lange       ilocal[point] = point;
63746f9b1c3SMichael Lange       iremote[point].index = p;
63846f9b1c3SMichael Lange       iremote[point].rank = rank;
63946f9b1c3SMichael Lange       depthIdx[d]++;
64046f9b1c3SMichael Lange     }
64146f9b1c3SMichael Lange   }
64246f9b1c3SMichael Lange 
64346f9b1c3SMichael Lange   /* Add in the remote roots for currently shared points */
6445f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(dm, &pointSF));
6455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(pointSF, NULL, &numSharedPoints, &sharedLocal, &sharedRemote));
64646f9b1c3SMichael Lange   for (d=0; d<dim+1; d++) {
6475f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
64846f9b1c3SMichael Lange     for (p=0; p<numSharedPoints; p++) {
64946f9b1c3SMichael Lange       if (pStart <= sharedLocal[p] && sharedLocal[p] < pEnd) {
65046f9b1c3SMichael Lange         point = sharedLocal[p] + depthShift[d];
65146f9b1c3SMichael Lange         iremote[point].index = sharedRemote[p].index;
65246f9b1c3SMichael Lange         iremote[point].rank = sharedRemote[p].rank;
65346f9b1c3SMichael Lange       }
65446f9b1c3SMichael Lange     }
65546f9b1c3SMichael Lange   }
65646f9b1c3SMichael Lange 
65746f9b1c3SMichael Lange   /* Now add the incoming overlap points */
65846f9b1c3SMichael Lange   for (p=0; p<nleaves; p++) {
65946f9b1c3SMichael Lange     point = depthIdx[remoteDepths[p]];
66046f9b1c3SMichael Lange     ilocal[point] = point;
66146f9b1c3SMichael Lange     iremote[point].index = overlapRemote[p].index;
66246f9b1c3SMichael Lange     iremote[point].rank = overlapRemote[p].rank;
66346f9b1c3SMichael Lange     depthIdx[remoteDepths[p]]++;
66446f9b1c3SMichael Lange   }
6655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(pointDepths,remoteDepths));
66646f9b1c3SMichael Lange 
6675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreate(comm, migrationSF));
6685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) *migrationSF, "Overlap Migration SF"));
6695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetFromOptions(*migrationSF));
6705f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
6715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetGraph(*migrationSF, pEnd-pStart, newLeaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER));
67246f9b1c3SMichael Lange 
6735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree3(depthRecv, depthShift, depthIdx));
67470034214SMatthew G. Knepley   PetscFunctionReturn(0);
67570034214SMatthew G. Knepley }
67670034214SMatthew G. Knepley 
677a9f1d5b2SMichael Lange /*@
678f0e73a3dSToby Isaac   DMPlexStratifyMigrationSF - Rearrange the leaves of a migration sf for stratification.
679a9f1d5b2SMichael Lange 
680064ec1f3Sprj-   Input Parameters:
681a9f1d5b2SMichael Lange + dm          - The DM
682a9f1d5b2SMichael Lange - sf          - A star forest with non-ordered leaves, usually defining a DM point migration
683a9f1d5b2SMichael Lange 
684a9f1d5b2SMichael Lange   Output Parameter:
685a9f1d5b2SMichael Lange . migrationSF - A star forest with added leaf indirection that ensures the resulting DM is stratified
686a9f1d5b2SMichael Lange 
687412e9a14SMatthew G. Knepley   Note:
688412e9a14SMatthew G. Knepley   This lexicographically sorts by (depth, cellType)
689412e9a14SMatthew G. Knepley 
690a9f1d5b2SMichael Lange   Level: developer
691a9f1d5b2SMichael Lange 
692a9f1d5b2SMichael Lange .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexDistributeOverlap()
693a9f1d5b2SMichael Lange @*/
694a9f1d5b2SMichael Lange PetscErrorCode DMPlexStratifyMigrationSF(DM dm, PetscSF sf, PetscSF *migrationSF)
695a9f1d5b2SMichael Lange {
696a9f1d5b2SMichael Lange   MPI_Comm           comm;
6979852e123SBarry Smith   PetscMPIInt        rank, size;
698412e9a14SMatthew G. Knepley   PetscInt           d, ldepth, depth, dim, p, pStart, pEnd, nroots, nleaves;
699412e9a14SMatthew G. Knepley   PetscSFNode       *pointDepths, *remoteDepths;
700412e9a14SMatthew G. Knepley   PetscInt          *ilocal;
701a9f1d5b2SMichael Lange   PetscInt          *depthRecv, *depthShift, *depthIdx;
702412e9a14SMatthew G. Knepley   PetscInt          *ctRecv,    *ctShift,    *ctIdx;
703a9f1d5b2SMichael Lange   const PetscSFNode *iremote;
704a9f1d5b2SMichael Lange 
705a9f1d5b2SMichael Lange   PetscFunctionBegin;
706a9f1d5b2SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm));
7085f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
7095f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
7105f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &ldepth));
7115f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
7125f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPIU_Allreduce(&ldepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
7132c71b3e2SJacob Faibussowitsch   PetscCheckFalse((ldepth >= 0) && (depth != ldepth),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %d != %d", ldepth, depth);
7145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_PartStratSF,dm,0,0,0));
715a9f1d5b2SMichael Lange 
716a9f1d5b2SMichael Lange   /* Before building the migration SF we need to know the new stratum offsets */
7175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, &iremote));
7185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths));
7197fab53ddSMatthew G. Knepley   for (d = 0; d < depth+1; ++d) {
7205f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
721f0e73a3dSToby Isaac     for (p = pStart; p < pEnd; ++p) {
722412e9a14SMatthew G. Knepley       DMPolytopeType ct;
723f0e73a3dSToby Isaac 
7245f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCellType(dm, p, &ct));
725412e9a14SMatthew G. Knepley       pointDepths[p].index = d;
726412e9a14SMatthew G. Knepley       pointDepths[p].rank  = ct;
727f0e73a3dSToby Isaac     }
728412e9a14SMatthew G. Knepley   }
729412e9a14SMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {remoteDepths[p].index = -1; remoteDepths[p].rank = -1;}
7305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(sf, MPIU_2INT, pointDepths, remoteDepths,MPI_REPLACE));
7315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(sf, MPIU_2INT, pointDepths, remoteDepths,MPI_REPLACE));
732412e9a14SMatthew G. Knepley   /* Count received points in each stratum and compute the internal strata shift */
7335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc6(depth+1, &depthRecv, depth+1, &depthShift, depth+1, &depthIdx, DM_NUM_POLYTOPES, &ctRecv, DM_NUM_POLYTOPES, &ctShift, DM_NUM_POLYTOPES, &ctIdx));
734412e9a14SMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
735412e9a14SMatthew G. Knepley     if (remoteDepths[p].rank < 0) {
736412e9a14SMatthew G. Knepley       ++depthRecv[remoteDepths[p].index];
737412e9a14SMatthew G. Knepley     } else {
738412e9a14SMatthew G. Knepley       ++ctRecv[remoteDepths[p].rank];
739412e9a14SMatthew G. Knepley     }
740412e9a14SMatthew G. Knepley   }
741412e9a14SMatthew G. Knepley   {
742412e9a14SMatthew G. Knepley     PetscInt depths[4], dims[4], shift = 0, i, c;
743412e9a14SMatthew G. Knepley 
7448238f61eSMatthew G. Knepley     /* Cells (depth), Vertices (0), Faces (depth-1), Edges (1)
7458238f61eSMatthew G. Knepley          Consider DM_POLYTOPE_FV_GHOST and DM_POLYTOPE_INTERIOR_GHOST as cells
7468238f61eSMatthew G. Knepley      */
747412e9a14SMatthew G. Knepley     depths[0] = depth; depths[1] = 0; depths[2] = depth-1; depths[3] = 1;
748412e9a14SMatthew G. Knepley     dims[0]   = dim;   dims[1]   = 0; dims[2]   = dim-1;   dims[3]   = 1;
749412e9a14SMatthew G. Knepley     for (i = 0; i <= depth; ++i) {
750412e9a14SMatthew G. Knepley       const PetscInt dep = depths[i];
751412e9a14SMatthew G. Knepley       const PetscInt dim = dims[i];
752412e9a14SMatthew G. Knepley 
753412e9a14SMatthew G. Knepley       for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
7548238f61eSMatthew G. Knepley         if (DMPolytopeTypeGetDim((DMPolytopeType) c) != dim && !(i == 0 && (c == DM_POLYTOPE_FV_GHOST || c == DM_POLYTOPE_INTERIOR_GHOST))) continue;
755412e9a14SMatthew G. Knepley         ctShift[c] = shift;
756412e9a14SMatthew G. Knepley         shift     += ctRecv[c];
757412e9a14SMatthew G. Knepley       }
758412e9a14SMatthew G. Knepley       depthShift[dep] = shift;
759412e9a14SMatthew G. Knepley       shift          += depthRecv[dep];
760412e9a14SMatthew G. Knepley     }
761412e9a14SMatthew G. Knepley     for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
762412e9a14SMatthew G. Knepley       const PetscInt ctDim = DMPolytopeTypeGetDim((DMPolytopeType) c);
763412e9a14SMatthew G. Knepley 
7648238f61eSMatthew G. Knepley       if ((ctDim < 0 || ctDim > dim) && (c != DM_POLYTOPE_FV_GHOST && c != DM_POLYTOPE_INTERIOR_GHOST)) {
765412e9a14SMatthew G. Knepley         ctShift[c] = shift;
766412e9a14SMatthew G. Knepley         shift     += ctRecv[c];
767412e9a14SMatthew G. Knepley       }
768412e9a14SMatthew G. Knepley     }
769412e9a14SMatthew G. Knepley   }
770a9f1d5b2SMichael Lange   /* Derive a new local permutation based on stratified indices */
7715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nleaves, &ilocal));
7727fab53ddSMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
773412e9a14SMatthew G. Knepley     const PetscInt       dep = remoteDepths[p].index;
774412e9a14SMatthew G. Knepley     const DMPolytopeType ct  = (DMPolytopeType) remoteDepths[p].rank;
7757fab53ddSMatthew G. Knepley 
776412e9a14SMatthew G. Knepley     if ((PetscInt) ct < 0) {
7777fab53ddSMatthew G. Knepley       ilocal[p] = depthShift[dep] + depthIdx[dep];
778412e9a14SMatthew G. Knepley       ++depthIdx[dep];
779412e9a14SMatthew G. Knepley     } else {
780412e9a14SMatthew G. Knepley       ilocal[p] = ctShift[ct] + ctIdx[ct];
781412e9a14SMatthew G. Knepley       ++ctIdx[ct];
782412e9a14SMatthew G. Knepley     }
783a9f1d5b2SMichael Lange   }
7845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreate(comm, migrationSF));
7855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) *migrationSF, "Migration SF"));
7865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetGraph(*migrationSF, nroots, nleaves, ilocal, PETSC_OWN_POINTER, (PetscSFNode*)iremote, PETSC_COPY_VALUES));
7875f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(pointDepths,remoteDepths));
7885f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree6(depthRecv, depthShift, depthIdx, ctRecv, ctShift, ctIdx));
7895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_PartStratSF,dm,0,0,0));
790a9f1d5b2SMichael Lange   PetscFunctionReturn(0);
791a9f1d5b2SMichael Lange }
792a9f1d5b2SMichael Lange 
79370034214SMatthew G. Knepley /*@
79470034214SMatthew G. Knepley   DMPlexDistributeField - Distribute field data to match a given PetscSF, usually the SF from mesh distribution
79570034214SMatthew G. Knepley 
796d083f849SBarry Smith   Collective on dm
79770034214SMatthew G. Knepley 
79870034214SMatthew G. Knepley   Input Parameters:
79970034214SMatthew G. Knepley + dm - The DMPlex object
80070034214SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern
80170034214SMatthew G. Knepley . originalSection - The PetscSection for existing data layout
802cb15cd0eSMatthew G. Knepley - originalVec - The existing data in a local vector
80370034214SMatthew G. Knepley 
80470034214SMatthew G. Knepley   Output Parameters:
80570034214SMatthew G. Knepley + newSection - The PetscSF describing the new data layout
806cb15cd0eSMatthew G. Knepley - newVec - The new data in a local vector
80770034214SMatthew G. Knepley 
80870034214SMatthew G. Knepley   Level: developer
80970034214SMatthew G. Knepley 
81070034214SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeFieldIS(), DMPlexDistributeData()
81170034214SMatthew G. Knepley @*/
81270034214SMatthew G. Knepley PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec)
81370034214SMatthew G. Knepley {
81470034214SMatthew G. Knepley   PetscSF        fieldSF;
81570034214SMatthew G. Knepley   PetscInt      *remoteOffsets, fieldSize;
81670034214SMatthew G. Knepley   PetscScalar   *originalValues, *newValues;
81770034214SMatthew G. Knepley 
81870034214SMatthew G. Knepley   PetscFunctionBegin;
8195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeField,dm,0,0,0));
8205f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection));
82170034214SMatthew G. Knepley 
8225f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(newSection, &fieldSize));
8235f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(newVec, fieldSize, PETSC_DETERMINE));
8245f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(newVec,dm->vectype));
82570034214SMatthew G. Knepley 
8265f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(originalVec, &originalValues));
8275f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(newVec, &newValues));
8285f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF));
8295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(remoteOffsets));
8305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues,MPI_REPLACE));
8315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues,MPI_REPLACE));
8325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&fieldSF));
8335f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(newVec, &newValues));
8345f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(originalVec, &originalValues));
8355f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeField,dm,0,0,0));
83670034214SMatthew G. Knepley   PetscFunctionReturn(0);
83770034214SMatthew G. Knepley }
83870034214SMatthew G. Knepley 
83970034214SMatthew G. Knepley /*@
84070034214SMatthew G. Knepley   DMPlexDistributeFieldIS - Distribute field data to match a given PetscSF, usually the SF from mesh distribution
84170034214SMatthew G. Knepley 
842d083f849SBarry Smith   Collective on dm
84370034214SMatthew G. Knepley 
84470034214SMatthew G. Knepley   Input Parameters:
84570034214SMatthew G. Knepley + dm - The DMPlex object
84670034214SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern
84770034214SMatthew G. Knepley . originalSection - The PetscSection for existing data layout
84870034214SMatthew G. Knepley - originalIS - The existing data
84970034214SMatthew G. Knepley 
85070034214SMatthew G. Knepley   Output Parameters:
85170034214SMatthew G. Knepley + newSection - The PetscSF describing the new data layout
85270034214SMatthew G. Knepley - newIS - The new data
85370034214SMatthew G. Knepley 
85470034214SMatthew G. Knepley   Level: developer
85570034214SMatthew G. Knepley 
85670034214SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexDistributeData()
85770034214SMatthew G. Knepley @*/
85870034214SMatthew G. Knepley PetscErrorCode DMPlexDistributeFieldIS(DM dm, PetscSF pointSF, PetscSection originalSection, IS originalIS, PetscSection newSection, IS *newIS)
85970034214SMatthew G. Knepley {
86070034214SMatthew G. Knepley   PetscSF         fieldSF;
86170034214SMatthew G. Knepley   PetscInt       *newValues, *remoteOffsets, fieldSize;
86270034214SMatthew G. Knepley   const PetscInt *originalValues;
86370034214SMatthew G. Knepley 
86470034214SMatthew G. Knepley   PetscFunctionBegin;
8655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeField,dm,0,0,0));
8665f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection));
86770034214SMatthew G. Knepley 
8685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(newSection, &fieldSize));
8695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(fieldSize, &newValues));
87070034214SMatthew G. Knepley 
8715f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(originalIS, &originalValues));
8725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF));
8735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(remoteOffsets));
8745f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(fieldSF, MPIU_INT, (PetscInt *) originalValues, newValues,MPI_REPLACE));
8755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(fieldSF, MPIU_INT, (PetscInt *) originalValues, newValues,MPI_REPLACE));
8765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&fieldSF));
8775f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(originalIS, &originalValues));
8785f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject) pointSF), fieldSize, newValues, PETSC_OWN_POINTER, newIS));
8795f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeField,dm,0,0,0));
88070034214SMatthew G. Knepley   PetscFunctionReturn(0);
88170034214SMatthew G. Knepley }
88270034214SMatthew G. Knepley 
88370034214SMatthew G. Knepley /*@
88470034214SMatthew G. Knepley   DMPlexDistributeData - Distribute field data to match a given PetscSF, usually the SF from mesh distribution
88570034214SMatthew G. Knepley 
886d083f849SBarry Smith   Collective on dm
88770034214SMatthew G. Knepley 
88870034214SMatthew G. Knepley   Input Parameters:
88970034214SMatthew G. Knepley + dm - The DMPlex object
89070034214SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern
89170034214SMatthew G. Knepley . originalSection - The PetscSection for existing data layout
89270034214SMatthew G. Knepley . datatype - The type of data
89370034214SMatthew G. Knepley - originalData - The existing data
89470034214SMatthew G. Knepley 
89570034214SMatthew G. Knepley   Output Parameters:
89670034214SMatthew G. Knepley + newSection - The PetscSection describing the new data layout
89770034214SMatthew G. Knepley - newData - The new data
89870034214SMatthew G. Knepley 
89970034214SMatthew G. Knepley   Level: developer
90070034214SMatthew G. Knepley 
90170034214SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField()
90270034214SMatthew G. Knepley @*/
90370034214SMatthew G. Knepley PetscErrorCode DMPlexDistributeData(DM dm, PetscSF pointSF, PetscSection originalSection, MPI_Datatype datatype, void *originalData, PetscSection newSection, void **newData)
90470034214SMatthew G. Knepley {
90570034214SMatthew G. Knepley   PetscSF        fieldSF;
90670034214SMatthew G. Knepley   PetscInt      *remoteOffsets, fieldSize;
90770034214SMatthew G. Knepley   PetscMPIInt    dataSize;
90870034214SMatthew G. Knepley 
90970034214SMatthew G. Knepley   PetscFunctionBegin;
9105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeData,dm,0,0,0));
9115f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection));
91270034214SMatthew G. Knepley 
9135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(newSection, &fieldSize));
9145f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Type_size(datatype, &dataSize));
9155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc(fieldSize * dataSize, newData));
91670034214SMatthew G. Knepley 
9175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF));
9185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(remoteOffsets));
9195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(fieldSF, datatype, originalData, *newData,MPI_REPLACE));
9205f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(fieldSF, datatype, originalData, *newData,MPI_REPLACE));
9215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&fieldSF));
9225f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeData,dm,0,0,0));
92370034214SMatthew G. Knepley   PetscFunctionReturn(0);
92470034214SMatthew G. Knepley }
92570034214SMatthew G. Knepley 
92624cc2ca5SMatthew G. Knepley static PetscErrorCode DMPlexDistributeCones(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel)
927cc71bff1SMichael Lange {
928cc71bff1SMichael Lange   DM_Plex               *pmesh = (DM_Plex*) (dmParallel)->data;
929cc71bff1SMichael Lange   MPI_Comm               comm;
930cc71bff1SMichael Lange   PetscSF                coneSF;
931cc71bff1SMichael Lange   PetscSection           originalConeSection, newConeSection;
932ac04eaf7SToby Isaac   PetscInt              *remoteOffsets, *cones, *globCones, *newCones, newConesSize;
933cc71bff1SMichael Lange   PetscBool              flg;
934cc71bff1SMichael Lange 
935cc71bff1SMichael Lange   PetscFunctionBegin;
936cc71bff1SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9370c86c063SLisandro Dalcin   PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5);
9385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeCones,dm,0,0,0));
939cc71bff1SMichael Lange   /* Distribute cone section */
9405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm));
9415f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeSection(dm, &originalConeSection));
9425f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeSection(dmParallel, &newConeSection));
9435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDistributeSection(migrationSF, originalConeSection, &remoteOffsets, newConeSection));
9445f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetUp(dmParallel));
945cc71bff1SMichael Lange   {
946cc71bff1SMichael Lange     PetscInt pStart, pEnd, p;
947cc71bff1SMichael Lange 
9485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetChart(newConeSection, &pStart, &pEnd));
949cc71bff1SMichael Lange     for (p = pStart; p < pEnd; ++p) {
950cc71bff1SMichael Lange       PetscInt coneSize;
9515f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(newConeSection, p, &coneSize));
952cc71bff1SMichael Lange       pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize);
953cc71bff1SMichael Lange     }
954cc71bff1SMichael Lange   }
955cc71bff1SMichael Lange   /* Communicate and renumber cones */
9565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreateSectionSF(migrationSF, originalConeSection, remoteOffsets, newConeSection, &coneSF));
9575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(remoteOffsets));
9585f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCones(dm, &cones));
959ac04eaf7SToby Isaac   if (original) {
960ac04eaf7SToby Isaac     PetscInt numCones;
961ac04eaf7SToby Isaac 
9625f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(originalConeSection,&numCones));
9635f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(numCones,&globCones));
9645f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingApplyBlock(original, numCones, cones, globCones));
965367003a6SStefano Zampini   } else {
966ac04eaf7SToby Isaac     globCones = cones;
967ac04eaf7SToby Isaac   }
9685f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCones(dmParallel, &newCones));
9695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(coneSF, MPIU_INT, globCones, newCones,MPI_REPLACE));
9705f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(coneSF, MPIU_INT, globCones, newCones,MPI_REPLACE));
971ac04eaf7SToby Isaac   if (original) {
9725f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(globCones));
973ac04eaf7SToby Isaac   }
9745f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(newConeSection, &newConesSize));
9755f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones));
97676bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
9773533c52bSMatthew G. Knepley     PetscInt  p;
9783533c52bSMatthew G. Knepley     PetscBool valid = PETSC_TRUE;
9793533c52bSMatthew G. Knepley     for (p = 0; p < newConesSize; ++p) {
9805f80ce2aSJacob Faibussowitsch       if (newCones[p] < 0) {valid = PETSC_FALSE; CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "[%d] Point %D not in overlap SF\n", PetscGlobalRank,p));}
9813533c52bSMatthew G. Knepley     }
982*28b400f6SJacob Faibussowitsch     PetscCheck(valid,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map");
9833533c52bSMatthew G. Knepley   }
9845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-cones_view", &flg));
985cc71bff1SMichael Lange   if (flg) {
9865f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(comm, "Serial Cone Section:\n"));
9875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_(comm)));
9885f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(comm, "Parallel Cone Section:\n"));
9895f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_(comm)));
9905f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFView(coneSF, NULL));
991cc71bff1SMichael Lange   }
9925f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeOrientations(dm, &cones));
9935f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeOrientations(dmParallel, &newCones));
9945f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones,MPI_REPLACE));
9955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones,MPI_REPLACE));
9965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&coneSF));
9975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeCones,dm,0,0,0));
998eaf898f9SPatrick Sanan   /* Create supports and stratify DMPlex */
999cc71bff1SMichael Lange   {
1000cc71bff1SMichael Lange     PetscInt pStart, pEnd;
1001cc71bff1SMichael Lange 
10025f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd));
10035f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetChart(pmesh->supportSection, pStart, pEnd));
1004cc71bff1SMichael Lange   }
10055f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSymmetrize(dmParallel));
10065f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratify(dmParallel));
10071cf84007SMatthew G. Knepley   {
10081cf84007SMatthew G. Knepley     PetscBool useCone, useClosure, useAnchors;
10091cf84007SMatthew G. Knepley 
10105f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetBasicAdjacency(dm, &useCone, &useClosure));
10115f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetBasicAdjacency(dmParallel, useCone, useClosure));
10125f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors));
10135f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetAdjacencyUseAnchors(dmParallel, useAnchors));
10141cf84007SMatthew G. Knepley   }
1015cc71bff1SMichael Lange   PetscFunctionReturn(0);
1016cc71bff1SMichael Lange }
1017cc71bff1SMichael Lange 
101824cc2ca5SMatthew G. Knepley static PetscErrorCode DMPlexDistributeCoordinates(DM dm, PetscSF migrationSF, DM dmParallel)
10190df0e737SMichael Lange {
10200df0e737SMichael Lange   MPI_Comm         comm;
10219318fe57SMatthew G. Knepley   DM               cdm, cdmParallel;
10220df0e737SMichael Lange   PetscSection     originalCoordSection, newCoordSection;
10230df0e737SMichael Lange   Vec              originalCoordinates, newCoordinates;
10240df0e737SMichael Lange   PetscInt         bs;
102590b157c4SStefano Zampini   PetscBool        isper;
10260df0e737SMichael Lange   const char      *name;
10270df0e737SMichael Lange   const PetscReal *maxCell, *L;
10285dc8c3f7SMatthew G. Knepley   const DMBoundaryType *bd;
10290df0e737SMichael Lange 
10300df0e737SMichael Lange   PetscFunctionBegin;
10310df0e737SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10320c86c063SLisandro Dalcin   PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3);
10330df0e737SMichael Lange 
10345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm));
10355f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(dm, &originalCoordSection));
10365f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(dmParallel, &newCoordSection));
10375f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinatesLocal(dm, &originalCoordinates));
10380df0e737SMichael Lange   if (originalCoordinates) {
10395f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCreate(PETSC_COMM_SELF, &newCoordinates));
10405f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject) originalCoordinates, &name));
10415f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject) newCoordinates, name));
10420df0e737SMichael Lange 
10435f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates));
10445f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetCoordinatesLocal(dmParallel, newCoordinates));
10455f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetBlockSize(originalCoordinates, &bs));
10465f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetBlockSize(newCoordinates, bs));
10475f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&newCoordinates));
10480df0e737SMichael Lange   }
10495f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd));
10505f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetPeriodicity(dmParallel, isper, maxCell, L, bd));
10515f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(dm, &cdm));
10525f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(dmParallel, &cdmParallel));
10535f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCopyDisc(cdm, cdmParallel));
10540df0e737SMichael Lange   PetscFunctionReturn(0);
10550df0e737SMichael Lange }
10560df0e737SMichael Lange 
105724cc2ca5SMatthew G. Knepley static PetscErrorCode DMPlexDistributeLabels(DM dm, PetscSF migrationSF, DM dmParallel)
10580df0e737SMichael Lange {
1059df0420ecSMatthew G. Knepley   DM_Plex         *mesh = (DM_Plex*) dm->data;
10600df0e737SMichael Lange   MPI_Comm         comm;
10617980c9d4SMatthew G. Knepley   DMLabel          depthLabel;
10620df0e737SMichael Lange   PetscMPIInt      rank;
10637980c9d4SMatthew G. Knepley   PetscInt         depth, d, numLabels, numLocalLabels, l;
1064df0420ecSMatthew G. Knepley   PetscBool        hasLabels = PETSC_FALSE, lsendDepth, sendDepth;
1065df0420ecSMatthew G. Knepley   PetscObjectState depthState = -1;
10660df0e737SMichael Lange 
10670df0e737SMichael Lange   PetscFunctionBegin;
10680df0e737SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10690c86c063SLisandro Dalcin   PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3);
10700c86c063SLisandro Dalcin 
10715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeLabels,dm,0,0,0));
10725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm));
10735f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
10740df0e737SMichael Lange 
1075df0420ecSMatthew G. Knepley   /* If the user has changed the depth label, communicate it instead */
10765f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth));
10775f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthLabel(dm, &depthLabel));
10785f80ce2aSJacob Faibussowitsch   if (depthLabel) CHKERRQ(PetscObjectStateGet((PetscObject) depthLabel, &depthState));
1079df0420ecSMatthew G. Knepley   lsendDepth = mesh->depthState != depthState ? PETSC_TRUE : PETSC_FALSE;
10805f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPIU_Allreduce(&lsendDepth, &sendDepth, 1, MPIU_BOOL, MPI_LOR, comm));
1081df0420ecSMatthew G. Knepley   if (sendDepth) {
10825f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthLabel(dmParallel, &dmParallel->depthLabel));
10835f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRemoveLabelBySelf(dmParallel, &dmParallel->depthLabel, PETSC_FALSE));
1084df0420ecSMatthew G. Knepley   }
1085d995df53SMatthew G. Knepley   /* Everyone must have either the same number of labels, or none */
10865f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetNumLabels(dm, &numLocalLabels));
1087d995df53SMatthew G. Knepley   numLabels = numLocalLabels;
10885f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm));
1089627847f0SMatthew G. Knepley   if (numLabels == numLocalLabels) hasLabels = PETSC_TRUE;
10905d80c0bfSVaclav Hapla   for (l = 0; l < numLabels; ++l) {
1091bdd2d751SMichael Lange     DMLabel     label = NULL, labelNew = NULL;
109283e10cb3SLisandro Dalcin     PetscBool   isDepth, lisOutput = PETSC_TRUE, isOutput;
1093d67d17b1SMatthew G. Knepley     const char *name = NULL;
10940df0e737SMichael Lange 
1095d67d17b1SMatthew G. Knepley     if (hasLabels) {
10965f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetLabelByNum(dm, l, &label));
10970df0e737SMichael Lange       /* Skip "depth" because it is recreated */
10985f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectGetName((PetscObject) label, &name));
10995f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscStrcmp(name, "depth", &isDepth));
1100d67d17b1SMatthew G. Knepley     }
11015f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Bcast(&isDepth, 1, MPIU_BOOL, 0, comm));
110283e10cb3SLisandro Dalcin     if (isDepth && !sendDepth) continue;
11035f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelDistribute(label, migrationSF, &labelNew));
110483e10cb3SLisandro Dalcin     if (isDepth) {
11057980c9d4SMatthew G. Knepley       /* Put in any missing strata which can occur if users are managing the depth label themselves */
11067980c9d4SMatthew G. Knepley       PetscInt gdepth;
11077980c9d4SMatthew G. Knepley 
11085f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPIU_Allreduce(&depth, &gdepth, 1, MPIU_INT, MPI_MAX, comm));
11092c71b3e2SJacob Faibussowitsch       PetscCheckFalse((depth >= 0) && (gdepth != depth),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %d != %d", depth, gdepth);
11107980c9d4SMatthew G. Knepley       for (d = 0; d <= gdepth; ++d) {
11117980c9d4SMatthew G. Knepley         PetscBool has;
11127980c9d4SMatthew G. Knepley 
11135f80ce2aSJacob Faibussowitsch         CHKERRQ(DMLabelHasStratum(labelNew, d, &has));
11145f80ce2aSJacob Faibussowitsch         if (!has) CHKERRQ(DMLabelAddStratum(labelNew, d));
11157980c9d4SMatthew G. Knepley       }
11167980c9d4SMatthew G. Knepley     }
11175f80ce2aSJacob Faibussowitsch     CHKERRQ(DMAddLabel(dmParallel, labelNew));
111883e10cb3SLisandro Dalcin     /* Put the output flag in the new label */
11195f80ce2aSJacob Faibussowitsch     if (hasLabels) CHKERRQ(DMGetLabelOutput(dm, name, &lisOutput));
11205f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPIU_Allreduce(&lisOutput, &isOutput, 1, MPIU_BOOL, MPI_LAND, comm));
11215f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject) labelNew, &name));
11225f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetLabelOutput(dmParallel, name, isOutput));
11235f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelDestroy(&labelNew));
11240df0e737SMichael Lange   }
11255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeLabels,dm,0,0,0));
11260df0e737SMichael Lange   PetscFunctionReturn(0);
11270df0e737SMichael Lange }
11280df0e737SMichael Lange 
112924cc2ca5SMatthew G. Knepley static PetscErrorCode DMPlexDistributeSetupTree(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel)
1130a6f36705SMichael Lange {
113115078cd4SMichael Lange   DM_Plex        *mesh  = (DM_Plex*) dm->data;
113215078cd4SMichael Lange   DM_Plex        *pmesh = (DM_Plex*) (dmParallel)->data;
1133a6f36705SMichael Lange   MPI_Comm        comm;
1134a6f36705SMichael Lange   DM              refTree;
1135a6f36705SMichael Lange   PetscSection    origParentSection, newParentSection;
1136a6f36705SMichael Lange   PetscInt        *origParents, *origChildIDs;
1137a6f36705SMichael Lange   PetscBool       flg;
1138a6f36705SMichael Lange 
1139a6f36705SMichael Lange   PetscFunctionBegin;
1140a6f36705SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11410c86c063SLisandro Dalcin   PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5);
11425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm));
1143a6f36705SMichael Lange 
1144a6f36705SMichael Lange   /* Set up tree */
11455f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetReferenceTree(dm,&refTree));
11465f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetReferenceTree(dmParallel,refTree));
11475f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetTree(dm,&origParentSection,&origParents,&origChildIDs,NULL,NULL));
1148a6f36705SMichael Lange   if (origParentSection) {
1149a6f36705SMichael Lange     PetscInt        pStart, pEnd;
115008633170SToby Isaac     PetscInt        *newParents, *newChildIDs, *globParents;
1151a6f36705SMichael Lange     PetscInt        *remoteOffsetsParents, newParentSize;
1152a6f36705SMichael Lange     PetscSF         parentSF;
1153a6f36705SMichael Lange 
11545f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetChart(dmParallel, &pStart, &pEnd));
11555f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)dmParallel),&newParentSection));
11565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetChart(newParentSection,pStart,pEnd));
11575f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDistributeSection(migrationSF, origParentSection, &remoteOffsetsParents, newParentSection));
11585f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreateSectionSF(migrationSF, origParentSection, remoteOffsetsParents, newParentSection, &parentSF));
11595f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(remoteOffsetsParents));
11605f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(newParentSection,&newParentSize));
11615f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc2(newParentSize,&newParents,newParentSize,&newChildIDs));
116208633170SToby Isaac     if (original) {
116308633170SToby Isaac       PetscInt numParents;
116408633170SToby Isaac 
11655f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetStorageSize(origParentSection,&numParents));
11665f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(numParents,&globParents));
11675f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingApplyBlock(original, numParents, origParents, globParents));
116808633170SToby Isaac     }
116908633170SToby Isaac     else {
117008633170SToby Isaac       globParents = origParents;
117108633170SToby Isaac     }
11725f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(parentSF, MPIU_INT, globParents, newParents,MPI_REPLACE));
11735f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(parentSF, MPIU_INT, globParents, newParents,MPI_REPLACE));
117408633170SToby Isaac     if (original) {
11755f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(globParents));
117608633170SToby Isaac     }
11775f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(parentSF, MPIU_INT, origChildIDs, newChildIDs,MPI_REPLACE));
11785f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(parentSF, MPIU_INT, origChildIDs, newChildIDs,MPI_REPLACE));
11795f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGlobalToLocalMappingApplyBlock(renumbering,IS_GTOLM_MASK, newParentSize, newParents, NULL, newParents));
118076bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
11814a54e071SToby Isaac       PetscInt  p;
11824a54e071SToby Isaac       PetscBool valid = PETSC_TRUE;
11834a54e071SToby Isaac       for (p = 0; p < newParentSize; ++p) {
11845f80ce2aSJacob Faibussowitsch         if (newParents[p] < 0) {valid = PETSC_FALSE; CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "Point %d not in overlap SF\n", p));}
11854a54e071SToby Isaac       }
1186*28b400f6SJacob Faibussowitsch       PetscCheck(valid,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map");
11874a54e071SToby Isaac     }
11885f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-parents_view", &flg));
1189a6f36705SMichael Lange     if (flg) {
11905f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscPrintf(comm, "Serial Parent Section: \n"));
11915f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionView(origParentSection, PETSC_VIEWER_STDOUT_(comm)));
11925f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscPrintf(comm, "Parallel Parent Section: \n"));
11935f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionView(newParentSection, PETSC_VIEWER_STDOUT_(comm)));
11945f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSFView(parentSF, NULL));
1195a6f36705SMichael Lange     }
11965f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetTree(dmParallel,newParentSection,newParents,newChildIDs));
11975f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionDestroy(&newParentSection));
11985f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(newParents,newChildIDs));
11995f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&parentSF));
1200a6f36705SMichael Lange   }
120115078cd4SMichael Lange   pmesh->useAnchors = mesh->useAnchors;
1202a6f36705SMichael Lange   PetscFunctionReturn(0);
1203a6f36705SMichael Lange }
12040df0e737SMichael Lange 
120524cc2ca5SMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexDistributeSF(DM dm, PetscSF migrationSF, DM dmParallel)
12064eca1733SMichael Lange {
12079852e123SBarry Smith   PetscMPIInt            rank, size;
12084eca1733SMichael Lange   MPI_Comm               comm;
12094eca1733SMichael Lange 
12104eca1733SMichael Lange   PetscFunctionBegin;
12114eca1733SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
12120c86c063SLisandro Dalcin   PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3);
12134eca1733SMichael Lange 
12144eca1733SMichael Lange   /* Create point SF for parallel mesh */
12155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeSF,dm,0,0,0));
12165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm));
12175f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
12185f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
12194eca1733SMichael Lange   {
12204eca1733SMichael Lange     const PetscInt *leaves;
12214eca1733SMichael Lange     PetscSFNode    *remotePoints, *rowners, *lowners;
12224eca1733SMichael Lange     PetscInt        numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints;
12234eca1733SMichael Lange     PetscInt        pStart, pEnd;
12244eca1733SMichael Lange 
12255f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetChart(dmParallel, &pStart, &pEnd));
12265f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFGetGraph(migrationSF, &numRoots, &numLeaves, &leaves, NULL));
12275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc2(numRoots,&rowners,numLeaves,&lowners));
12284eca1733SMichael Lange     for (p=0; p<numRoots; p++) {
12294eca1733SMichael Lange       rowners[p].rank  = -1;
12304eca1733SMichael Lange       rowners[p].index = -1;
12314eca1733SMichael Lange     }
12325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(migrationSF, MPIU_2INT, rowners, lowners,MPI_REPLACE));
12335f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(migrationSF, MPIU_2INT, rowners, lowners,MPI_REPLACE));
12344eca1733SMichael Lange     for (p = 0; p < numLeaves; ++p) {
12354eca1733SMichael Lange       if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */
12364eca1733SMichael Lange         lowners[p].rank  = rank;
12374eca1733SMichael Lange         lowners[p].index = leaves ? leaves[p] : p;
12384eca1733SMichael Lange       } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */
12394eca1733SMichael Lange         lowners[p].rank  = -2;
12404eca1733SMichael Lange         lowners[p].index = -2;
12414eca1733SMichael Lange       }
12424eca1733SMichael Lange     }
12434eca1733SMichael Lange     for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */
12444eca1733SMichael Lange       rowners[p].rank  = -3;
12454eca1733SMichael Lange       rowners[p].index = -3;
12464eca1733SMichael Lange     }
12475f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceBegin(migrationSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC));
12485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceEnd(migrationSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC));
12495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(migrationSF, MPIU_2INT, rowners, lowners,MPI_REPLACE));
12505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(migrationSF, MPIU_2INT, rowners, lowners,MPI_REPLACE));
12514eca1733SMichael Lange     for (p = 0; p < numLeaves; ++p) {
12522c71b3e2SJacob Faibussowitsch       PetscCheckFalse(lowners[p].rank < 0 || lowners[p].index < 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed");
12534eca1733SMichael Lange       if (lowners[p].rank != rank) ++numGhostPoints;
12544eca1733SMichael Lange     }
12555f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(numGhostPoints, &ghostPoints));
12565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(numGhostPoints, &remotePoints));
12574eca1733SMichael Lange     for (p = 0, gp = 0; p < numLeaves; ++p) {
12584eca1733SMichael Lange       if (lowners[p].rank != rank) {
12594eca1733SMichael Lange         ghostPoints[gp]        = leaves ? leaves[p] : p;
12604eca1733SMichael Lange         remotePoints[gp].rank  = lowners[p].rank;
12614eca1733SMichael Lange         remotePoints[gp].index = lowners[p].index;
12624eca1733SMichael Lange         ++gp;
12634eca1733SMichael Lange       }
12644eca1733SMichael Lange     }
12655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(rowners,lowners));
12665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFSetGraph((dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER));
12675f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFSetFromOptions((dmParallel)->sf));
12684eca1733SMichael Lange   }
12691cf84007SMatthew G. Knepley   {
12701cf84007SMatthew G. Knepley     PetscBool useCone, useClosure, useAnchors;
12711cf84007SMatthew G. Knepley 
12725f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetBasicAdjacency(dm, &useCone, &useClosure));
12735f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetBasicAdjacency(dmParallel, useCone, useClosure));
12745f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors));
12755f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexSetAdjacencyUseAnchors(dmParallel, useAnchors));
12761cf84007SMatthew G. Knepley   }
12775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeSF,dm,0,0,0));
12784eca1733SMichael Lange   PetscFunctionReturn(0);
12794eca1733SMichael Lange }
12804eca1733SMichael Lange 
128198ba2d7fSLawrence Mitchell /*@
128298ba2d7fSLawrence Mitchell   DMPlexSetPartitionBalance - Should distribution of the DM attempt to balance the shared point partition?
128398ba2d7fSLawrence Mitchell 
128498ba2d7fSLawrence Mitchell   Input Parameters:
128598ba2d7fSLawrence Mitchell + dm - The DMPlex object
128698ba2d7fSLawrence Mitchell - flg - Balance the partition?
128798ba2d7fSLawrence Mitchell 
128898ba2d7fSLawrence Mitchell   Level: intermediate
128998ba2d7fSLawrence Mitchell 
129098ba2d7fSLawrence Mitchell .seealso: DMPlexDistribute(), DMPlexGetPartitionBalance()
129198ba2d7fSLawrence Mitchell @*/
129298ba2d7fSLawrence Mitchell PetscErrorCode DMPlexSetPartitionBalance(DM dm, PetscBool flg)
129398ba2d7fSLawrence Mitchell {
129498ba2d7fSLawrence Mitchell   DM_Plex *mesh = (DM_Plex *)dm->data;
129598ba2d7fSLawrence Mitchell 
129698ba2d7fSLawrence Mitchell   PetscFunctionBegin;
129798ba2d7fSLawrence Mitchell   mesh->partitionBalance = flg;
129898ba2d7fSLawrence Mitchell   PetscFunctionReturn(0);
129998ba2d7fSLawrence Mitchell }
130098ba2d7fSLawrence Mitchell 
130198ba2d7fSLawrence Mitchell /*@
130298ba2d7fSLawrence Mitchell   DMPlexGetPartitionBalance - Does distribution of the DM attempt to balance the shared point partition?
130398ba2d7fSLawrence Mitchell 
130498ba2d7fSLawrence Mitchell   Input Parameter:
1305a2b725a8SWilliam Gropp . dm - The DMPlex object
130698ba2d7fSLawrence Mitchell 
130798ba2d7fSLawrence Mitchell   Output Parameter:
1308a2b725a8SWilliam Gropp . flg - Balance the partition?
130998ba2d7fSLawrence Mitchell 
131098ba2d7fSLawrence Mitchell   Level: intermediate
131198ba2d7fSLawrence Mitchell 
131298ba2d7fSLawrence Mitchell .seealso: DMPlexDistribute(), DMPlexSetPartitionBalance()
131398ba2d7fSLawrence Mitchell @*/
131498ba2d7fSLawrence Mitchell PetscErrorCode DMPlexGetPartitionBalance(DM dm, PetscBool *flg)
131598ba2d7fSLawrence Mitchell {
131698ba2d7fSLawrence Mitchell   DM_Plex *mesh = (DM_Plex *)dm->data;
131798ba2d7fSLawrence Mitchell 
131898ba2d7fSLawrence Mitchell   PetscFunctionBegin;
131998ba2d7fSLawrence Mitchell   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1320534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
132198ba2d7fSLawrence Mitchell   *flg = mesh->partitionBalance;
132298ba2d7fSLawrence Mitchell   PetscFunctionReturn(0);
132398ba2d7fSLawrence Mitchell }
132498ba2d7fSLawrence Mitchell 
1325fc02256fSLawrence Mitchell typedef struct {
1326fc02256fSLawrence Mitchell   PetscInt vote, rank, index;
1327fc02256fSLawrence Mitchell } Petsc3Int;
1328fc02256fSLawrence Mitchell 
1329fc02256fSLawrence Mitchell /* MaxLoc, but carry a third piece of information around */
13302eb0eadbSSatish Balay static void MPIAPI MaxLocCarry(void *in_, void *inout_, PetscMPIInt *len_, MPI_Datatype *dtype)
1331fc02256fSLawrence Mitchell {
1332fc02256fSLawrence Mitchell   Petsc3Int *a = (Petsc3Int *)inout_;
1333fc02256fSLawrence Mitchell   Petsc3Int *b = (Petsc3Int *)in_;
1334fc02256fSLawrence Mitchell   PetscInt i, len = *len_;
1335fc02256fSLawrence Mitchell   for (i = 0; i < len; i++) {
1336fc02256fSLawrence Mitchell     if (a[i].vote < b[i].vote) {
1337fc02256fSLawrence Mitchell       a[i].vote = b[i].vote;
1338fc02256fSLawrence Mitchell       a[i].rank = b[i].rank;
1339fc02256fSLawrence Mitchell       a[i].index = b[i].index;
1340fc02256fSLawrence Mitchell     } else if (a[i].vote <= b[i].vote) {
1341fc02256fSLawrence Mitchell       if (a[i].rank >= b[i].rank) {
1342fc02256fSLawrence Mitchell         a[i].rank = b[i].rank;
1343fc02256fSLawrence Mitchell         a[i].index = b[i].index;
1344fc02256fSLawrence Mitchell       }
1345fc02256fSLawrence Mitchell     }
1346fc02256fSLawrence Mitchell   }
1347fc02256fSLawrence Mitchell }
1348fc02256fSLawrence Mitchell 
1349f5bf2dbfSMichael Lange /*@C
1350a8c5bd36SStefano Zampini   DMPlexCreatePointSF - Build a point SF from an SF describing a point migration
1351f5bf2dbfSMichael Lange 
1352064ec1f3Sprj-   Input Parameters:
1353f5bf2dbfSMichael Lange + dm          - The source DMPlex object
1354f5bf2dbfSMichael Lange . migrationSF - The star forest that describes the parallel point remapping
1355d8d19677SJose E. Roman - ownership   - Flag causing a vote to determine point ownership
1356f5bf2dbfSMichael Lange 
1357f5bf2dbfSMichael Lange   Output Parameter:
1358d8d19677SJose E. Roman . pointSF     - The star forest describing the point overlap in the remapped DM
1359f5bf2dbfSMichael Lange 
13603618482eSVaclav Hapla   Notes:
13613618482eSVaclav Hapla   Output pointSF is guaranteed to have the array of local indices (leaves) sorted.
13623618482eSVaclav Hapla 
1363f5bf2dbfSMichael Lange   Level: developer
1364f5bf2dbfSMichael Lange 
1365f5bf2dbfSMichael Lange .seealso: DMPlexDistribute(), DMPlexDistributeOverlap()
1366f5bf2dbfSMichael Lange @*/
1367f5bf2dbfSMichael Lange PetscErrorCode DMPlexCreatePointSF(DM dm, PetscSF migrationSF, PetscBool ownership, PetscSF *pointSF)
1368f5bf2dbfSMichael Lange {
136923193802SMatthew G. Knepley   PetscMPIInt        rank, size;
13701627f6ccSMichael Lange   PetscInt           p, nroots, nleaves, idx, npointLeaves;
1371f5bf2dbfSMichael Lange   PetscInt          *pointLocal;
1372f5bf2dbfSMichael Lange   const PetscInt    *leaves;
1373f5bf2dbfSMichael Lange   const PetscSFNode *roots;
1374f5bf2dbfSMichael Lange   PetscSFNode       *rootNodes, *leafNodes, *pointRemote;
137523193802SMatthew G. Knepley   Vec                shifts;
1376cae3e4f3SLawrence Mitchell   const PetscInt     numShifts = 13759;
137723193802SMatthew G. Knepley   const PetscScalar *shift = NULL;
137823193802SMatthew G. Knepley   const PetscBool    shiftDebug = PETSC_FALSE;
137998ba2d7fSLawrence Mitchell   PetscBool          balance;
1380f5bf2dbfSMichael Lange 
1381f5bf2dbfSMichael Lange   PetscFunctionBegin;
1382f5bf2dbfSMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
13835f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
13845f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size));
13855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_CreatePointSF,dm,0,0,0));
1386f5bf2dbfSMichael Lange 
13875f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetPartitionBalance(dm, &balance));
13885f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(migrationSF, &nroots, &nleaves, &leaves, &roots));
13895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(nroots, &rootNodes, nleaves, &leafNodes));
1390f5bf2dbfSMichael Lange   if (ownership) {
1391fc02256fSLawrence Mitchell     MPI_Op       op;
1392fc02256fSLawrence Mitchell     MPI_Datatype datatype;
1393fc02256fSLawrence Mitchell     Petsc3Int   *rootVote = NULL, *leafVote = NULL;
139423193802SMatthew G. Knepley     /* If balancing, we compute a random cyclic shift of the rank for each remote point. That way, the max will evenly distribute among ranks. */
139598ba2d7fSLawrence Mitchell     if (balance) {
139623193802SMatthew G. Knepley       PetscRandom r;
139723193802SMatthew G. Knepley 
13985f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscRandomCreate(PETSC_COMM_SELF, &r));
13995f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscRandomSetInterval(r, 0, 2467*size));
14005f80ce2aSJacob Faibussowitsch       CHKERRQ(VecCreate(PETSC_COMM_SELF, &shifts));
14015f80ce2aSJacob Faibussowitsch       CHKERRQ(VecSetSizes(shifts, numShifts, numShifts));
14025f80ce2aSJacob Faibussowitsch       CHKERRQ(VecSetType(shifts, VECSTANDARD));
14035f80ce2aSJacob Faibussowitsch       CHKERRQ(VecSetRandom(shifts, r));
14045f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscRandomDestroy(&r));
14055f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArrayRead(shifts, &shift));
140623193802SMatthew G. Knepley     }
140723193802SMatthew G. Knepley 
14085f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nroots, &rootVote));
14095f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nleaves, &leafVote));
141023193802SMatthew G. Knepley     /* Point ownership vote: Process with highest rank owns shared points */
1411f5bf2dbfSMichael Lange     for (p = 0; p < nleaves; ++p) {
141223193802SMatthew G. Knepley       if (shiftDebug) {
14135f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Point %D RemotePoint %D Shift %D MyRank %D\n", rank, leaves ? leaves[p] : p, roots[p].index, (PetscInt) PetscRealPart(shift[roots[p].index%numShifts]), (rank + (shift ? (PetscInt) PetscRealPart(shift[roots[p].index%numShifts]) : 0))%size));
141423193802SMatthew G. Knepley       }
1415f5bf2dbfSMichael Lange       /* Either put in a bid or we know we own it */
1416fc02256fSLawrence Mitchell       leafVote[p].vote  = (rank + (shift ? (PetscInt) PetscRealPart(shift[roots[p].index%numShifts]) : 0))%size;
1417fc02256fSLawrence Mitchell       leafVote[p].rank = rank;
1418fc02256fSLawrence Mitchell       leafVote[p].index = p;
1419f5bf2dbfSMichael Lange     }
1420f5bf2dbfSMichael Lange     for (p = 0; p < nroots; p++) {
14211627f6ccSMichael Lange       /* Root must not participate in the reduction, flag so that MAXLOC does not use */
1422fc02256fSLawrence Mitchell       rootVote[p].vote  = -3;
1423fc02256fSLawrence Mitchell       rootVote[p].rank  = -3;
1424fc02256fSLawrence Mitchell       rootVote[p].index = -3;
1425f5bf2dbfSMichael Lange     }
14265f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_contiguous(3, MPIU_INT, &datatype));
14275f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_commit(&datatype));
14285f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Op_create(&MaxLocCarry, 1, &op));
14295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceBegin(migrationSF, datatype, leafVote, rootVote, op));
14305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceEnd(migrationSF, datatype, leafVote, rootVote, op));
14315f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Op_free(&op));
14325f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_free(&datatype));
1433c091126eSLawrence Mitchell     for (p = 0; p < nroots; p++) {
1434fc02256fSLawrence Mitchell       rootNodes[p].rank = rootVote[p].rank;
1435fc02256fSLawrence Mitchell       rootNodes[p].index = rootVote[p].index;
1436c091126eSLawrence Mitchell     }
14375f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(leafVote));
14385f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(rootVote));
1439f5bf2dbfSMichael Lange   } else {
1440f5bf2dbfSMichael Lange     for (p = 0; p < nroots; p++) {
1441f5bf2dbfSMichael Lange       rootNodes[p].index = -1;
1442f5bf2dbfSMichael Lange       rootNodes[p].rank = rank;
1443fc02256fSLawrence Mitchell     }
1444f5bf2dbfSMichael Lange     for (p = 0; p < nleaves; p++) {
1445f5bf2dbfSMichael Lange       /* Write new local id into old location */
1446f5bf2dbfSMichael Lange       if (roots[p].rank == rank) {
14476462276dSToby Isaac         rootNodes[roots[p].index].index = leaves ? leaves[p] : p;
1448f5bf2dbfSMichael Lange       }
1449f5bf2dbfSMichael Lange     }
1450f5bf2dbfSMichael Lange   }
14515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(migrationSF, MPIU_2INT, rootNodes, leafNodes,MPI_REPLACE));
14525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(migrationSF, MPIU_2INT, rootNodes, leafNodes,MPI_REPLACE));
1453f5bf2dbfSMichael Lange 
145423193802SMatthew G. Knepley   for (npointLeaves = 0, p = 0; p < nleaves; p++) {
1455b0e1264bSMatthew G. Knepley     if (leafNodes[p].rank != rank) npointLeaves++;
145623193802SMatthew G. Knepley   }
14575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(npointLeaves, &pointLocal));
14585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(npointLeaves, &pointRemote));
1459f5bf2dbfSMichael Lange   for (idx = 0, p = 0; p < nleaves; p++) {
1460b0e1264bSMatthew G. Knepley     if (leafNodes[p].rank != rank) {
14613618482eSVaclav Hapla       /* Note that pointLocal is automatically sorted as it is sublist of 0, ..., nleaves-1 */
1462f5bf2dbfSMichael Lange       pointLocal[idx] = p;
1463f5bf2dbfSMichael Lange       pointRemote[idx] = leafNodes[p];
1464f5bf2dbfSMichael Lange       idx++;
1465f5bf2dbfSMichael Lange     }
1466f5bf2dbfSMichael Lange   }
146723193802SMatthew G. Knepley   if (shift) {
14685f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(shifts, &shift));
14695f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&shifts));
147023193802SMatthew G. Knepley   }
14715f80ce2aSJacob Faibussowitsch   if (shiftDebug) CHKERRQ(PetscSynchronizedFlush(PetscObjectComm((PetscObject) dm), PETSC_STDOUT));
14725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreate(PetscObjectComm((PetscObject) dm), pointSF));
14735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetFromOptions(*pointSF));
14745f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetGraph(*pointSF, nleaves, npointLeaves, pointLocal, PETSC_OWN_POINTER, pointRemote, PETSC_OWN_POINTER));
14755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(rootNodes, leafNodes));
14765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_CreatePointSF,dm,0,0,0));
1477f5bf2dbfSMichael Lange   PetscFunctionReturn(0);
1478f5bf2dbfSMichael Lange }
1479f5bf2dbfSMichael Lange 
148015078cd4SMichael Lange /*@C
148115078cd4SMichael Lange   DMPlexMigrate  - Migrates internal DM data over the supplied star forest
148215078cd4SMichael Lange 
1483d083f849SBarry Smith   Collective on dm
148483655b49SVáclav Hapla 
1485064ec1f3Sprj-   Input Parameters:
148615078cd4SMichael Lange + dm       - The source DMPlex object
1487d8d19677SJose E. Roman - sf       - The star forest communication context describing the migration pattern
148815078cd4SMichael Lange 
148915078cd4SMichael Lange   Output Parameter:
1490d8d19677SJose E. Roman . targetDM - The target DMPlex object
149115078cd4SMichael Lange 
1492b9f40539SMichael Lange   Level: intermediate
149315078cd4SMichael Lange 
149415078cd4SMichael Lange .seealso: DMPlexDistribute(), DMPlexDistributeOverlap()
149515078cd4SMichael Lange @*/
1496b9f40539SMichael Lange PetscErrorCode DMPlexMigrate(DM dm, PetscSF sf, DM targetDM)
149715078cd4SMichael Lange {
1498b9f40539SMichael Lange   MPI_Comm               comm;
1499cc1750acSStefano Zampini   PetscInt               dim, cdim, nroots;
1500b9f40539SMichael Lange   PetscSF                sfPoint;
150115078cd4SMichael Lange   ISLocalToGlobalMapping ltogMigration;
1502ac04eaf7SToby Isaac   ISLocalToGlobalMapping ltogOriginal = NULL;
1503b9f40539SMichael Lange   PetscBool              flg;
150415078cd4SMichael Lange 
150515078cd4SMichael Lange   PetscFunctionBegin;
150615078cd4SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
15075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_Migrate, dm, 0, 0, 0));
15085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm));
15095f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
15105f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(targetDM, dim));
15115f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDim(dm, &cdim));
15125f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinateDim(targetDM, cdim));
151315078cd4SMichael Lange 
1514bfb0467fSMichael Lange   /* Check for a one-to-all distribution pattern */
15155f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(dm, &sfPoint));
15165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
1517bfb0467fSMichael Lange   if (nroots >= 0) {
1518b9f40539SMichael Lange     IS        isOriginal;
1519ac04eaf7SToby Isaac     PetscInt  n, size, nleaves;
1520ac04eaf7SToby Isaac     PetscInt  *numbering_orig, *numbering_new;
1521367003a6SStefano Zampini 
1522b9f40539SMichael Lange     /* Get the original point numbering */
15235f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreatePointNumbering(dm, &isOriginal));
15245f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreateIS(isOriginal, &ltogOriginal));
15255f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetSize(ltogOriginal, &size));
15265f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetBlockIndices(ltogOriginal, (const PetscInt**)&numbering_orig));
1527b9f40539SMichael Lange     /* Convert to positive global numbers */
1528b9f40539SMichael Lange     for (n=0; n<size; n++) {if (numbering_orig[n] < 0) numbering_orig[n] = -(numbering_orig[n]+1);}
1529b9f40539SMichael Lange     /* Derive the new local-to-global mapping from the old one */
15305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFGetGraph(sf, NULL, &nleaves, NULL, NULL));
15315f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nleaves, &numbering_new));
15325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(sf, MPIU_INT, numbering_orig, numbering_new,MPI_REPLACE));
15335f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(sf, MPIU_INT, numbering_orig, numbering_new,MPI_REPLACE));
15345f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreate(comm, 1, nleaves, numbering_new, PETSC_OWN_POINTER, &ltogMigration));
15355f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingRestoreIndices(ltogOriginal, (const PetscInt**)&numbering_orig));
15365f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&isOriginal));
153715078cd4SMichael Lange   } else {
1538bfb0467fSMichael Lange     /* One-to-all distribution pattern: We can derive LToG from SF */
15395f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreateSF(sf, 0, &ltogMigration));
154015078cd4SMichael Lange   }
15415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-partition_view", &flg));
1542b9f40539SMichael Lange   if (flg) {
15435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(comm, "Point renumbering for DM migration:\n"));
15445f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingView(ltogMigration, NULL));
1545b9f40539SMichael Lange   }
154615078cd4SMichael Lange   /* Migrate DM data to target DM */
15475f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexDistributeCones(dm, sf, ltogOriginal, ltogMigration, targetDM));
15485f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexDistributeLabels(dm, sf, targetDM));
15495f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexDistributeCoordinates(dm, sf, targetDM));
15505f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexDistributeSetupTree(dm, sf, ltogOriginal, ltogMigration, targetDM));
15515f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&ltogOriginal));
15525f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&ltogMigration));
15535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_Migrate, dm, 0, 0, 0));
155415078cd4SMichael Lange   PetscFunctionReturn(0);
155515078cd4SMichael Lange }
155615078cd4SMichael Lange 
15573b8f15a2SMatthew G. Knepley /*@C
155870034214SMatthew G. Knepley   DMPlexDistribute - Distributes the mesh and any associated sections.
155970034214SMatthew G. Knepley 
1560d083f849SBarry Smith   Collective on dm
156170034214SMatthew G. Knepley 
1562064ec1f3Sprj-   Input Parameters:
156370034214SMatthew G. Knepley + dm  - The original DMPlex object
156470034214SMatthew G. Knepley - overlap - The overlap of partitions, 0 is the default
156570034214SMatthew G. Knepley 
1566064ec1f3Sprj-   Output Parameters:
1567f4ae5380SJed Brown + sf - The PetscSF used for point distribution, or NULL if not needed
1568f4ae5380SJed Brown - dmParallel - The distributed DMPlex object
156970034214SMatthew G. Knepley 
1570f4ae5380SJed Brown   Note: If the mesh was not distributed, the output dmParallel will be NULL.
157170034214SMatthew G. Knepley 
1572b0441da4SMatthew G. Knepley   The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function
157370034214SMatthew G. Knepley   representation on the mesh.
157470034214SMatthew G. Knepley 
157570034214SMatthew G. Knepley   Level: intermediate
157670034214SMatthew G. Knepley 
1577cb54e036SVaclav Hapla .seealso: DMPlexCreate(), DMSetAdjacency(), DMPlexGetOverlap()
157870034214SMatthew G. Knepley @*/
157980cf41d5SMatthew G. Knepley PetscErrorCode DMPlexDistribute(DM dm, PetscInt overlap, PetscSF *sf, DM *dmParallel)
158070034214SMatthew G. Knepley {
158170034214SMatthew G. Knepley   MPI_Comm               comm;
158215078cd4SMichael Lange   PetscPartitioner       partitioner;
1583f8987ae8SMichael Lange   IS                     cellPart;
1584f8987ae8SMichael Lange   PetscSection           cellPartSection;
1585cf86098cSMatthew G. Knepley   DM                     dmCoord;
1586f8987ae8SMichael Lange   DMLabel                lblPartition, lblMigration;
1587874ddda9SLisandro Dalcin   PetscSF                sfMigration, sfStratified, sfPoint;
158898ba2d7fSLawrence Mitchell   PetscBool              flg, balance;
1589874ddda9SLisandro Dalcin   PetscMPIInt            rank, size;
159070034214SMatthew G. Knepley 
159170034214SMatthew G. Knepley   PetscFunctionBegin;
159270034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1593d5c515a1SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, overlap, 2);
1594d5c515a1SMatthew G. Knepley   if (sf) PetscValidPointer(sf,3);
1595d5c515a1SMatthew G. Knepley   PetscValidPointer(dmParallel,4);
159670034214SMatthew G. Knepley 
15970c86c063SLisandro Dalcin   if (sf) *sf = NULL;
15980c86c063SLisandro Dalcin   *dmParallel = NULL;
15995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm,&comm));
16005f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
16015f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
16020c86c063SLisandro Dalcin   if (size == 1) PetscFunctionReturn(0);
160370034214SMatthew G. Knepley 
16045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0));
160515078cd4SMichael Lange   /* Create cell partition */
16065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_Partition,dm,0,0,0));
16075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(comm, &cellPartSection));
16085f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetPartitioner(dm, &partitioner));
16095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPartitionerDMPlexPartition(partitioner, dm, NULL, cellPartSection, &cellPart));
16105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_PartSelf,dm,0,0,0));
1611f8987ae8SMichael Lange   {
1612f8987ae8SMichael Lange     /* Convert partition to DMLabel */
1613825f8a23SLisandro Dalcin     IS             is;
1614825f8a23SLisandro Dalcin     PetscHSetI     ht;
1615f8987ae8SMichael Lange     const PetscInt *points;
16168e330a33SStefano Zampini     PetscInt       *iranks;
16178e330a33SStefano Zampini     PetscInt       pStart, pEnd, proc, npoints, poff = 0, nranks;
1618825f8a23SLisandro Dalcin 
16195f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelCreate(PETSC_COMM_SELF, "Point Partition", &lblPartition));
1620825f8a23SLisandro Dalcin     /* Preallocate strata */
16215f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetICreate(&ht));
16225f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetChart(cellPartSection, &pStart, &pEnd));
1623825f8a23SLisandro Dalcin     for (proc = pStart; proc < pEnd; proc++) {
16245f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(cellPartSection, proc, &npoints));
16255f80ce2aSJacob Faibussowitsch       if (npoints) CHKERRQ(PetscHSetIAdd(ht, proc));
1626825f8a23SLisandro Dalcin     }
16275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetIGetSize(ht, &nranks));
16285f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nranks, &iranks));
16295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetIGetElems(ht, &poff, iranks));
16305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetIDestroy(&ht));
16315f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelAddStrata(lblPartition, nranks, iranks));
16325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(iranks));
1633825f8a23SLisandro Dalcin     /* Inline DMPlexPartitionLabelClosure() */
16345f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(cellPart, &points));
16355f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetChart(cellPartSection, &pStart, &pEnd));
1636f8987ae8SMichael Lange     for (proc = pStart; proc < pEnd; proc++) {
16375f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(cellPartSection, proc, &npoints));
1638825f8a23SLisandro Dalcin       if (!npoints) continue;
16395f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(cellPartSection, proc, &poff));
16405f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexClosurePoints_Private(dm, npoints, points+poff, &is));
16415f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelSetStratumIS(lblPartition, proc, is));
16425f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&is));
1643f8987ae8SMichael Lange     }
16445f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(cellPart, &points));
1645f8987ae8SMichael Lange   }
16465f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_PartSelf,dm,0,0,0));
16476e203dd9SStefano Zampini 
16485f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelCreate(PETSC_COMM_SELF, "Point migration", &lblMigration));
16495f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexPartitionLabelInvert(dm, lblPartition, NULL, lblMigration));
16505f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexPartitionLabelCreateSF(dm, lblMigration, &sfMigration));
16515f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratifyMigrationSF(dm, sfMigration, &sfStratified));
16525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&sfMigration));
165343f7d02bSMichael Lange   sfMigration = sfStratified;
16545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetUp(sfMigration));
16555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_Partition,dm,0,0,0));
16565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-partition_view", &flg));
165770034214SMatthew G. Knepley   if (flg) {
16585f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelView(lblPartition, PETSC_VIEWER_STDOUT_(comm)));
16595f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFView(sfMigration, PETSC_VIEWER_STDOUT_(comm)));
166070034214SMatthew G. Knepley   }
1661f8987ae8SMichael Lange 
166215078cd4SMichael Lange   /* Create non-overlapping parallel DM and migrate internal data */
16635f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreate(comm, dmParallel));
16645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh"));
16655f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexMigrate(dm, sfMigration, *dmParallel));
166670034214SMatthew G. Knepley 
1667a157612eSMichael Lange   /* Build the point SF without overlap */
16685f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetPartitionBalance(dm, &balance));
16695f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetPartitionBalance(*dmParallel, balance));
16705f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreatePointSF(*dmParallel, sfMigration, PETSC_TRUE, &sfPoint));
16715f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetPointSF(*dmParallel, sfPoint));
16725f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(*dmParallel, &dmCoord));
16735f80ce2aSJacob Faibussowitsch   if (dmCoord) CHKERRQ(DMSetPointSF(dmCoord, sfPoint));
16745f80ce2aSJacob Faibussowitsch   if (flg) CHKERRQ(PetscSFView(sfPoint, NULL));
167570034214SMatthew G. Knepley 
1676a157612eSMichael Lange   if (overlap > 0) {
167715078cd4SMichael Lange     DM                 dmOverlap;
167857f290daSMatthew G. Knepley     PetscInt           nroots, nleaves, noldleaves, l;
167957f290daSMatthew G. Knepley     const PetscInt    *oldLeaves;
168057f290daSMatthew G. Knepley     PetscSFNode       *newRemote, *permRemote;
168115078cd4SMichael Lange     const PetscSFNode *oldRemote;
168215078cd4SMichael Lange     PetscSF            sfOverlap, sfOverlapPoint;
1683524e35f8SStefano Zampini 
1684a157612eSMichael Lange     /* Add the partition overlap to the distributed DM */
16855f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexDistributeOverlap(*dmParallel, overlap, &sfOverlap, &dmOverlap));
16865f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDestroy(dmParallel));
1687a157612eSMichael Lange     *dmParallel = dmOverlap;
1688c389ea9fSToby Isaac     if (flg) {
16895f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscPrintf(comm, "Overlap Migration SF:\n"));
16905f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSFView(sfOverlap, NULL));
1691c389ea9fSToby Isaac     }
169243331d4aSMichael Lange 
1693f8987ae8SMichael Lange     /* Re-map the migration SF to establish the full migration pattern */
16945f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFGetGraph(sfMigration, &nroots, &noldleaves, &oldLeaves, &oldRemote));
16955f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFGetGraph(sfOverlap, NULL, &nleaves, NULL, NULL));
16965f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nleaves, &newRemote));
169757f290daSMatthew G. Knepley     /* oldRemote: original root point mapping to original leaf point
169857f290daSMatthew G. Knepley        newRemote: original leaf point mapping to overlapped leaf point */
169957f290daSMatthew G. Knepley     if (oldLeaves) {
170073e69a6aSMatthew G. Knepley       /* After stratification, the migration remotes may not be in root (canonical) order, so we reorder using the leaf numbering */
17015f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(noldleaves, &permRemote));
170257f290daSMatthew G. Knepley       for (l = 0; l < noldleaves; ++l) permRemote[oldLeaves[l]] = oldRemote[l];
170357f290daSMatthew G. Knepley       oldRemote = permRemote;
170457f290daSMatthew G. Knepley     }
17055f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(sfOverlap, MPIU_2INT, oldRemote, newRemote,MPI_REPLACE));
17065f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(sfOverlap, MPIU_2INT, oldRemote, newRemote,MPI_REPLACE));
17075f80ce2aSJacob Faibussowitsch     if (oldLeaves) CHKERRQ(PetscFree(oldRemote));
17085f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreate(comm, &sfOverlapPoint));
17095f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFSetGraph(sfOverlapPoint, nroots, nleaves, NULL, PETSC_OWN_POINTER, newRemote, PETSC_OWN_POINTER));
17105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&sfOverlap));
17115f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&sfMigration));
171215078cd4SMichael Lange     sfMigration = sfOverlapPoint;
1713c389ea9fSToby Isaac   }
1714bf5244c7SMatthew G. Knepley   /* Cleanup Partition */
17155f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelDestroy(&lblPartition));
17165f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelDestroy(&lblMigration));
17175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&cellPartSection));
17185f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&cellPart));
171945480ffeSMatthew G. Knepley   /* Copy discretization */
17205f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCopyDisc(dm, *dmParallel));
172166fe0bfeSMatthew G. Knepley   /* Create sfNatural */
172266fe0bfeSMatthew G. Knepley   if (dm->useNatural) {
172366fe0bfeSMatthew G. Knepley     PetscSection section;
172466fe0bfeSMatthew G. Knepley 
17255f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLocalSection(dm, &section));
17265f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateGlobalToNaturalSF(*dmParallel, section, sfMigration, &(*dmParallel)->sfNatural));
17275f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetUseNatural(*dmParallel, PETSC_TRUE));
172866fe0bfeSMatthew G. Knepley   }
17295f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCopy_Internal(dm, PETSC_TRUE, *dmParallel));
1730721cbd76SMatthew G. Knepley   /* Cleanup */
1731f8987ae8SMichael Lange   if (sf) {*sf = sfMigration;}
17325f80ce2aSJacob Faibussowitsch   else    CHKERRQ(PetscSFDestroy(&sfMigration));
17335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&sfPoint));
17345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0));
173570034214SMatthew G. Knepley   PetscFunctionReturn(0);
173670034214SMatthew G. Knepley }
1737a157612eSMichael Lange 
1738a157612eSMichael Lange /*@C
173924cc2ca5SMatthew G. Knepley   DMPlexDistributeOverlap - Add partition overlap to a distributed non-overlapping DM.
1740a157612eSMichael Lange 
1741d083f849SBarry Smith   Collective on dm
1742a157612eSMichael Lange 
1743064ec1f3Sprj-   Input Parameters:
1744064ec1f3Sprj- + dm  - The non-overlapping distributed DMPlex object
174557fe9a49SVaclav Hapla - overlap - The overlap of partitions (the same on all ranks)
1746a157612eSMichael Lange 
1747064ec1f3Sprj-   Output Parameters:
1748a157612eSMichael Lange + sf - The PetscSF used for point distribution
1749a157612eSMichael Lange - dmOverlap - The overlapping distributed DMPlex object, or NULL
1750a157612eSMichael Lange 
1751dccdeccaSVaclav Hapla   Notes:
1752dccdeccaSVaclav Hapla   If the mesh was not distributed, the return value is NULL.
1753a157612eSMichael Lange 
1754b0441da4SMatthew G. Knepley   The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function
1755a157612eSMichael Lange   representation on the mesh.
1756a157612eSMichael Lange 
1757dccdeccaSVaclav Hapla   Level: advanced
1758a157612eSMichael Lange 
1759cb54e036SVaclav Hapla .seealso: DMPlexCreate(), DMSetAdjacency(), DMPlexDistribute(), DMPlexCreateOverlapLabel(), DMPlexGetOverlap()
1760a157612eSMichael Lange @*/
1761b9f40539SMichael Lange PetscErrorCode DMPlexDistributeOverlap(DM dm, PetscInt overlap, PetscSF *sf, DM *dmOverlap)
1762a157612eSMichael Lange {
1763a157612eSMichael Lange   MPI_Comm               comm;
17643567eaeeSMatthew G. Knepley   PetscMPIInt            size, rank;
1765a157612eSMichael Lange   PetscSection           rootSection, leafSection;
1766a157612eSMichael Lange   IS                     rootrank, leafrank;
1767cf86098cSMatthew G. Knepley   DM                     dmCoord;
1768a9f1d5b2SMichael Lange   DMLabel                lblOverlap;
1769f5bf2dbfSMichael Lange   PetscSF                sfOverlap, sfStratified, sfPoint;
1770a157612eSMichael Lange 
1771a157612eSMichael Lange   PetscFunctionBegin;
1772a157612eSMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
177357fe9a49SVaclav Hapla   PetscValidLogicalCollectiveInt(dm, overlap, 2);
1774a157612eSMichael Lange   if (sf) PetscValidPointer(sf, 3);
1775a157612eSMichael Lange   PetscValidPointer(dmOverlap, 4);
1776a157612eSMichael Lange 
17770c86c063SLisandro Dalcin   if (sf) *sf = NULL;
17780c86c063SLisandro Dalcin   *dmOverlap  = NULL;
17795f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm,&comm));
17805f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
17815f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
17820c86c063SLisandro Dalcin   if (size == 1) PetscFunctionReturn(0);
1783a157612eSMichael Lange 
17845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeOverlap, dm, 0, 0, 0));
1785a157612eSMichael Lange   /* Compute point overlap with neighbouring processes on the distributed DM */
17865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_Partition,dm,0,0,0));
17875f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(comm, &rootSection));
17885f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(comm, &leafSection));
17895f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexDistributeOwnership(dm, rootSection, &rootrank, leafSection, &leafrank));
17905f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateOverlapLabel(dm, overlap, rootSection, rootrank, leafSection, leafrank, &lblOverlap));
1791a9f1d5b2SMichael Lange   /* Convert overlap label to stratified migration SF */
17925f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexPartitionLabelCreateSF(dm, lblOverlap, &sfOverlap));
17935f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratifyMigrationSF(dm, sfOverlap, &sfStratified));
17945f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&sfOverlap));
1795a9f1d5b2SMichael Lange   sfOverlap = sfStratified;
17965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) sfOverlap, "Overlap SF"));
17975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetFromOptions(sfOverlap));
1798a9f1d5b2SMichael Lange 
17995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&rootSection));
18005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&leafSection));
18015f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&rootrank));
18025f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&leafrank));
18035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_Partition,dm,0,0,0));
1804a157612eSMichael Lange 
1805a157612eSMichael Lange   /* Build the overlapping DM */
18065f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreate(comm, dmOverlap));
18075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) *dmOverlap, "Parallel Mesh"));
18085f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexMigrate(dm, sfOverlap, *dmOverlap));
1809cb54e036SVaclav Hapla   /* Store the overlap in the new DM */
1810cb54e036SVaclav Hapla   ((DM_Plex*)(*dmOverlap)->data)->overlap = overlap + ((DM_Plex*)dm->data)->overlap;
1811f5bf2dbfSMichael Lange   /* Build the new point SF */
18125f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreatePointSF(*dmOverlap, sfOverlap, PETSC_FALSE, &sfPoint));
18135f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetPointSF(*dmOverlap, sfPoint));
18145f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(*dmOverlap, &dmCoord));
18155f80ce2aSJacob Faibussowitsch   if (dmCoord) CHKERRQ(DMSetPointSF(dmCoord, sfPoint));
18165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&sfPoint));
1817a157612eSMichael Lange   /* Cleanup overlap partition */
18185f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelDestroy(&lblOverlap));
1819a9f1d5b2SMichael Lange   if (sf) *sf = sfOverlap;
18205f80ce2aSJacob Faibussowitsch   else    CHKERRQ(PetscSFDestroy(&sfOverlap));
18215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeOverlap, dm, 0, 0, 0));
1822a157612eSMichael Lange   PetscFunctionReturn(0);
1823a157612eSMichael Lange }
18246462276dSToby Isaac 
1825cb54e036SVaclav Hapla PetscErrorCode DMPlexGetOverlap_Plex(DM dm, PetscInt *overlap)
1826cb54e036SVaclav Hapla {
1827cb54e036SVaclav Hapla   DM_Plex        *mesh  = (DM_Plex*) dm->data;
1828cb54e036SVaclav Hapla 
1829cb54e036SVaclav Hapla   PetscFunctionBegin;
1830cb54e036SVaclav Hapla   *overlap = mesh->overlap;
1831cb54e036SVaclav Hapla   PetscFunctionReturn(0);
1832cb54e036SVaclav Hapla }
1833cb54e036SVaclav Hapla 
1834cb54e036SVaclav Hapla /*@
1835cb54e036SVaclav Hapla   DMPlexGetOverlap - Get the DMPlex partition overlap.
1836cb54e036SVaclav Hapla 
1837cb54e036SVaclav Hapla   Not collective
1838cb54e036SVaclav Hapla 
1839cb54e036SVaclav Hapla   Input Parameter:
1840cb54e036SVaclav Hapla . dm - The DM
1841cb54e036SVaclav Hapla 
1842064ec1f3Sprj-   Output Parameter:
1843cb54e036SVaclav Hapla . overlap - The overlap of this DM
1844cb54e036SVaclav Hapla 
1845cb54e036SVaclav Hapla   Level: intermediate
1846cb54e036SVaclav Hapla 
1847cb54e036SVaclav Hapla .seealso: DMPlexDistribute(), DMPlexDistributeOverlap(), DMPlexCreateOverlapLabel()
1848cb54e036SVaclav Hapla @*/
1849cb54e036SVaclav Hapla PetscErrorCode DMPlexGetOverlap(DM dm, PetscInt *overlap)
1850cb54e036SVaclav Hapla {
1851cb54e036SVaclav Hapla   PetscFunctionBegin;
1852cb54e036SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(dm,"DMPlexGetOverlap_C",(DM,PetscInt*),(dm,overlap)));
1854cb54e036SVaclav Hapla   PetscFunctionReturn(0);
1855cb54e036SVaclav Hapla }
1856cb54e036SVaclav Hapla 
1857e600fa54SMatthew G. Knepley PetscErrorCode DMPlexDistributeSetDefault_Plex(DM dm, PetscBool dist)
1858e600fa54SMatthew G. Knepley {
1859e600fa54SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *) dm->data;
1860e600fa54SMatthew G. Knepley 
1861e600fa54SMatthew G. Knepley   PetscFunctionBegin;
1862e600fa54SMatthew G. Knepley   mesh->distDefault = dist;
1863e600fa54SMatthew G. Knepley   PetscFunctionReturn(0);
1864e600fa54SMatthew G. Knepley }
1865e600fa54SMatthew G. Knepley 
1866e600fa54SMatthew G. Knepley /*@
1867e600fa54SMatthew G. Knepley   DMPlexDistributeSetDefault - Set flag indicating whether the DM should be distributed by default
1868e600fa54SMatthew G. Knepley 
1869e600fa54SMatthew G. Knepley   Logically collective
1870e600fa54SMatthew G. Knepley 
1871e600fa54SMatthew G. Knepley   Input Parameters:
1872e600fa54SMatthew G. Knepley + dm   - The DM
1873e600fa54SMatthew G. Knepley - dist - Flag for distribution
1874e600fa54SMatthew G. Knepley 
1875e600fa54SMatthew G. Knepley   Level: intermediate
1876e600fa54SMatthew G. Knepley 
1877e600fa54SMatthew G. Knepley .seealso: DMDistributeGetDefault(), DMPlexDistribute()
1878e600fa54SMatthew G. Knepley @*/
1879e600fa54SMatthew G. Knepley PetscErrorCode DMPlexDistributeSetDefault(DM dm, PetscBool dist)
1880e600fa54SMatthew G. Knepley {
1881e600fa54SMatthew G. Knepley   PetscFunctionBegin;
1882e600fa54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1883e600fa54SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, dist, 2);
18845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(dm,"DMPlexDistributeSetDefault_C",(DM,PetscBool),(dm,dist)));
1885e600fa54SMatthew G. Knepley   PetscFunctionReturn(0);
1886e600fa54SMatthew G. Knepley }
1887e600fa54SMatthew G. Knepley 
1888e600fa54SMatthew G. Knepley PetscErrorCode DMPlexDistributeGetDefault_Plex(DM dm, PetscBool *dist)
1889e600fa54SMatthew G. Knepley {
1890e600fa54SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *) dm->data;
1891e600fa54SMatthew G. Knepley 
1892e600fa54SMatthew G. Knepley   PetscFunctionBegin;
1893e600fa54SMatthew G. Knepley   *dist = mesh->distDefault;
1894e600fa54SMatthew G. Knepley   PetscFunctionReturn(0);
1895e600fa54SMatthew G. Knepley }
1896e600fa54SMatthew G. Knepley 
1897e600fa54SMatthew G. Knepley /*@
1898e600fa54SMatthew G. Knepley   DMPlexDistributeGetDefault - Get flag indicating whether the DM should be distributed by default
1899e600fa54SMatthew G. Knepley 
1900e600fa54SMatthew G. Knepley   Not collective
1901e600fa54SMatthew G. Knepley 
1902e600fa54SMatthew G. Knepley   Input Parameter:
1903e600fa54SMatthew G. Knepley . dm   - The DM
1904e600fa54SMatthew G. Knepley 
1905e600fa54SMatthew G. Knepley   Output Parameter:
1906e600fa54SMatthew G. Knepley . dist - Flag for distribution
1907e600fa54SMatthew G. Knepley 
1908e600fa54SMatthew G. Knepley   Level: intermediate
1909e600fa54SMatthew G. Knepley 
1910e600fa54SMatthew G. Knepley .seealso: DMDistributeSetDefault(), DMPlexDistribute()
1911e600fa54SMatthew G. Knepley @*/
1912e600fa54SMatthew G. Knepley PetscErrorCode DMPlexDistributeGetDefault(DM dm, PetscBool *dist)
1913e600fa54SMatthew G. Knepley {
1914e600fa54SMatthew G. Knepley   PetscFunctionBegin;
1915e600fa54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1916e600fa54SMatthew G. Knepley   PetscValidBoolPointer(dist, 2);
19175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(dm,"DMPlexDistributeGetDefault_C",(DM,PetscBool*),(dm,dist)));
1918e600fa54SMatthew G. Knepley   PetscFunctionReturn(0);
1919e600fa54SMatthew G. Knepley }
1920e600fa54SMatthew G. Knepley 
19216462276dSToby Isaac /*@C
19226462276dSToby Isaac   DMPlexGetGatherDM - Get a copy of the DMPlex that gathers all points on the
19236462276dSToby Isaac   root process of the original's communicator.
19246462276dSToby Isaac 
1925d083f849SBarry Smith   Collective on dm
192683655b49SVáclav Hapla 
1927064ec1f3Sprj-   Input Parameter:
19286462276dSToby Isaac . dm - the original DMPlex object
19296462276dSToby Isaac 
19306462276dSToby Isaac   Output Parameters:
1931a13df41bSStefano Zampini + sf - the PetscSF used for point distribution (optional)
1932a13df41bSStefano Zampini - gatherMesh - the gathered DM object, or NULL
19336462276dSToby Isaac 
19346462276dSToby Isaac   Level: intermediate
19356462276dSToby Isaac 
19366462276dSToby Isaac .seealso: DMPlexDistribute(), DMPlexGetRedundantDM()
19376462276dSToby Isaac @*/
1938a13df41bSStefano Zampini PetscErrorCode DMPlexGetGatherDM(DM dm, PetscSF *sf, DM *gatherMesh)
19396462276dSToby Isaac {
19406462276dSToby Isaac   MPI_Comm       comm;
19416462276dSToby Isaac   PetscMPIInt    size;
19426462276dSToby Isaac   PetscPartitioner oldPart, gatherPart;
19436462276dSToby Isaac 
19446462276dSToby Isaac   PetscFunctionBegin;
19456462276dSToby Isaac   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1946064a246eSJacob Faibussowitsch   PetscValidPointer(gatherMesh,3);
19470c86c063SLisandro Dalcin   *gatherMesh = NULL;
1948a13df41bSStefano Zampini   if (sf) *sf = NULL;
19496462276dSToby Isaac   comm = PetscObjectComm((PetscObject)dm);
19505f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm,&size));
19516462276dSToby Isaac   if (size == 1) PetscFunctionReturn(0);
19525f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetPartitioner(dm,&oldPart));
19535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)oldPart));
19545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPartitionerCreate(comm,&gatherPart));
19555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPartitionerSetType(gatherPart,PETSCPARTITIONERGATHER));
19565f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetPartitioner(dm,gatherPart));
19575f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexDistribute(dm,0,sf,gatherMesh));
1958a13df41bSStefano Zampini 
19595f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetPartitioner(dm,oldPart));
19605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPartitionerDestroy(&gatherPart));
19615f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPartitionerDestroy(&oldPart));
19626462276dSToby Isaac   PetscFunctionReturn(0);
19636462276dSToby Isaac }
19646462276dSToby Isaac 
19656462276dSToby Isaac /*@C
19666462276dSToby Isaac   DMPlexGetRedundantDM - Get a copy of the DMPlex that is completely copied on each process.
19676462276dSToby Isaac 
1968d083f849SBarry Smith   Collective on dm
196983655b49SVáclav Hapla 
1970064ec1f3Sprj-   Input Parameter:
19716462276dSToby Isaac . dm - the original DMPlex object
19726462276dSToby Isaac 
19736462276dSToby Isaac   Output Parameters:
1974a13df41bSStefano Zampini + sf - the PetscSF used for point distribution (optional)
1975a13df41bSStefano Zampini - redundantMesh - the redundant DM object, or NULL
19766462276dSToby Isaac 
19776462276dSToby Isaac   Level: intermediate
19786462276dSToby Isaac 
19796462276dSToby Isaac .seealso: DMPlexDistribute(), DMPlexGetGatherDM()
19806462276dSToby Isaac @*/
1981a13df41bSStefano Zampini PetscErrorCode DMPlexGetRedundantDM(DM dm, PetscSF *sf, DM *redundantMesh)
19826462276dSToby Isaac {
19836462276dSToby Isaac   MPI_Comm       comm;
19846462276dSToby Isaac   PetscMPIInt    size, rank;
19856462276dSToby Isaac   PetscInt       pStart, pEnd, p;
19866462276dSToby Isaac   PetscInt       numPoints = -1;
1987a13df41bSStefano Zampini   PetscSF        migrationSF, sfPoint, gatherSF;
19886462276dSToby Isaac   DM             gatherDM, dmCoord;
19896462276dSToby Isaac   PetscSFNode    *points;
19906462276dSToby Isaac 
19916462276dSToby Isaac   PetscFunctionBegin;
19926462276dSToby Isaac   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1993064a246eSJacob Faibussowitsch   PetscValidPointer(redundantMesh,3);
19940c86c063SLisandro Dalcin   *redundantMesh = NULL;
19956462276dSToby Isaac   comm = PetscObjectComm((PetscObject)dm);
19965f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm,&size));
199768dbc166SMatthew G. Knepley   if (size == 1) {
19985f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject) dm));
199968dbc166SMatthew G. Knepley     *redundantMesh = dm;
2000a13df41bSStefano Zampini     if (sf) *sf = NULL;
200168dbc166SMatthew G. Knepley     PetscFunctionReturn(0);
200268dbc166SMatthew G. Knepley   }
20035f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetGatherDM(dm,&gatherSF,&gatherDM));
20046462276dSToby Isaac   if (!gatherDM) PetscFunctionReturn(0);
20055f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm,&rank));
20065f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(gatherDM,&pStart,&pEnd));
20076462276dSToby Isaac   numPoints = pEnd - pStart;
20085f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(&numPoints,1,MPIU_INT,0,comm));
20095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(numPoints,&points));
20105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreate(comm,&migrationSF));
20116462276dSToby Isaac   for (p = 0; p < numPoints; p++) {
20126462276dSToby Isaac     points[p].index = p;
20136462276dSToby Isaac     points[p].rank  = 0;
20146462276dSToby Isaac   }
20155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetGraph(migrationSF,pEnd-pStart,numPoints,NULL,PETSC_OWN_POINTER,points,PETSC_OWN_POINTER));
20165f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreate(comm, redundantMesh));
20175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) *redundantMesh, "Redundant Mesh"));
20185f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexMigrate(gatherDM, migrationSF, *redundantMesh));
20195f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreatePointSF(*redundantMesh, migrationSF, PETSC_FALSE, &sfPoint));
20205f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetPointSF(*redundantMesh, sfPoint));
20215f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(*redundantMesh, &dmCoord));
20225f80ce2aSJacob Faibussowitsch   if (dmCoord) CHKERRQ(DMSetPointSF(dmCoord, sfPoint));
20235f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&sfPoint));
2024a13df41bSStefano Zampini   if (sf) {
2025a13df41bSStefano Zampini     PetscSF tsf;
2026a13df41bSStefano Zampini 
20275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCompose(gatherSF,migrationSF,&tsf));
20285f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexStratifyMigrationSF(dm, tsf, sf));
20295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&tsf));
2030a13df41bSStefano Zampini   }
20315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&migrationSF));
20325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&gatherSF));
20335f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&gatherDM));
20345f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCopyDisc(dm, *redundantMesh));
20355f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCopy_Internal(dm, PETSC_TRUE, *redundantMesh));
20366462276dSToby Isaac   PetscFunctionReturn(0);
20376462276dSToby Isaac }
20385fa78c88SVaclav Hapla 
20395fa78c88SVaclav Hapla /*@
20405fa78c88SVaclav Hapla   DMPlexIsDistributed - Find out whether this DM is distributed, i.e. more than one rank owns some points.
20415fa78c88SVaclav Hapla 
20425fa78c88SVaclav Hapla   Collective
20435fa78c88SVaclav Hapla 
20445fa78c88SVaclav Hapla   Input Parameter:
20455fa78c88SVaclav Hapla . dm      - The DM object
20465fa78c88SVaclav Hapla 
20475fa78c88SVaclav Hapla   Output Parameter:
20485fa78c88SVaclav Hapla . distributed - Flag whether the DM is distributed
20495fa78c88SVaclav Hapla 
20505fa78c88SVaclav Hapla   Level: intermediate
20515fa78c88SVaclav Hapla 
20525fa78c88SVaclav Hapla   Notes:
20535fa78c88SVaclav Hapla   This currently finds out whether at least two ranks have any DAG points.
20545fa78c88SVaclav Hapla   This involves MPI_Allreduce() with one integer.
20555fa78c88SVaclav Hapla   The result is currently not stashed so every call to this routine involves this global communication.
20565fa78c88SVaclav Hapla 
20575fa78c88SVaclav Hapla .seealso: DMPlexDistribute(), DMPlexGetOverlap(), DMPlexIsInterpolated()
20585fa78c88SVaclav Hapla @*/
20595fa78c88SVaclav Hapla PetscErrorCode DMPlexIsDistributed(DM dm, PetscBool *distributed)
20605fa78c88SVaclav Hapla {
20615fa78c88SVaclav Hapla   PetscInt          pStart, pEnd, count;
20625fa78c88SVaclav Hapla   MPI_Comm          comm;
206335d70e31SStefano Zampini   PetscMPIInt       size;
20645fa78c88SVaclav Hapla 
20655fa78c88SVaclav Hapla   PetscFunctionBegin;
20665fa78c88SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20675fa78c88SVaclav Hapla   PetscValidPointer(distributed,2);
20685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm,&comm));
20695f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm,&size));
207035d70e31SStefano Zampini   if (size == 1) { *distributed = PETSC_FALSE; PetscFunctionReturn(0); }
20715f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
207235d70e31SStefano Zampini   count = (pEnd - pStart) > 0 ? 1 : 0;
20735f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Allreduce(MPI_IN_PLACE, &count, 1, MPIU_INT, MPI_SUM, comm));
20745fa78c88SVaclav Hapla   *distributed = count > 1 ? PETSC_TRUE : PETSC_FALSE;
20755fa78c88SVaclav Hapla   PetscFunctionReturn(0);
20765fa78c88SVaclav Hapla }
2077