1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/
2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/
33b9d9b65SStefano Zampini #include <petsc/private/partitionerimpl.h>
470034214SMatthew G. Knepley
53c1f0c11SLawrence Mitchell /*@C
63c1f0c11SLawrence Mitchell DMPlexSetAdjacencyUser - Define adjacency in the mesh using a user-provided callback
73c1f0c11SLawrence Mitchell
83c1f0c11SLawrence Mitchell Input Parameters:
93c1f0c11SLawrence Mitchell + dm - The DM object
1020f4b53cSBarry Smith . user - The user callback, may be `NULL` (to clear the callback)
1120f4b53cSBarry Smith - ctx - context for callback evaluation, may be `NULL`
123c1f0c11SLawrence Mitchell
133c1f0c11SLawrence Mitchell Level: advanced
143c1f0c11SLawrence Mitchell
153c1f0c11SLawrence Mitchell Notes:
1620f4b53cSBarry Smith The caller of `DMPlexGetAdjacency()` may need to arrange that a large enough array is available for the adjacency.
173c1f0c11SLawrence Mitchell
1820f4b53cSBarry Smith Any setting here overrides other configuration of `DMPLEX` adjacency determination.
193c1f0c11SLawrence Mitchell
2020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMPlexPreallocateOperator()`, `DMPlexGetAdjacency()`, `DMPlexGetAdjacencyUser()`
213c1f0c11SLawrence Mitchell @*/
DMPlexSetAdjacencyUser(DM dm,PetscErrorCode (* user)(DM,PetscInt,PetscInt *,PetscInt[],void *),PetscCtx ctx)222a8381b2SBarry Smith PetscErrorCode DMPlexSetAdjacencyUser(DM dm, PetscErrorCode (*user)(DM, PetscInt, PetscInt *, PetscInt[], void *), PetscCtx ctx)
23d71ae5a4SJacob Faibussowitsch {
243c1f0c11SLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data;
253c1f0c11SLawrence Mitchell
263c1f0c11SLawrence Mitchell PetscFunctionBegin;
273c1f0c11SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
283c1f0c11SLawrence Mitchell mesh->useradjacency = user;
293c1f0c11SLawrence Mitchell mesh->useradjacencyctx = ctx;
303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
313c1f0c11SLawrence Mitchell }
323c1f0c11SLawrence Mitchell
333c1f0c11SLawrence Mitchell /*@C
343c1f0c11SLawrence Mitchell DMPlexGetAdjacencyUser - get the user-defined adjacency callback
353c1f0c11SLawrence Mitchell
363c1f0c11SLawrence Mitchell Input Parameter:
3720f4b53cSBarry Smith . dm - The `DM` object
383c1f0c11SLawrence Mitchell
393c1f0c11SLawrence Mitchell Output Parameters:
40ef1023bdSBarry Smith + user - The callback
413c1f0c11SLawrence Mitchell - ctx - context for callback evaluation
423c1f0c11SLawrence Mitchell
433c1f0c11SLawrence Mitchell Level: advanced
443c1f0c11SLawrence Mitchell
4520f4b53cSBarry Smith .seealso: `DMPLEX`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMPlexPreallocateOperator()`, `DMPlexGetAdjacency()`, `DMPlexSetAdjacencyUser()`
463c1f0c11SLawrence Mitchell @*/
DMPlexGetAdjacencyUser(DM dm,PetscErrorCode (** user)(DM,PetscInt,PetscInt *,PetscInt[],void *),void ** ctx)47d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAdjacencyUser(DM dm, PetscErrorCode (**user)(DM, PetscInt, PetscInt *, PetscInt[], void *), void **ctx)
48d71ae5a4SJacob Faibussowitsch {
493c1f0c11SLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data;
503c1f0c11SLawrence Mitchell
513c1f0c11SLawrence Mitchell PetscFunctionBegin;
523c1f0c11SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
533c1f0c11SLawrence Mitchell if (user) *user = mesh->useradjacency;
543c1f0c11SLawrence Mitchell if (ctx) *ctx = mesh->useradjacencyctx;
553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
563c1f0c11SLawrence Mitchell }
573c1f0c11SLawrence Mitchell
5870034214SMatthew G. Knepley /*@
59a17985deSToby Isaac DMPlexSetAdjacencyUseAnchors - Define adjacency in the mesh using the point-to-point constraints.
608b0b4c70SToby Isaac
618b0b4c70SToby Isaac Input Parameters:
6220f4b53cSBarry Smith + dm - The `DM` object
635b317d89SToby 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.
648b0b4c70SToby Isaac
658b0b4c70SToby Isaac Level: intermediate
668b0b4c70SToby Isaac
6720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMGetAdjacency()`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMPlexPreallocateOperator()`, `DMPlexSetAnchors()`
688b0b4c70SToby Isaac @*/
DMPlexSetAdjacencyUseAnchors(DM dm,PetscBool useAnchors)69d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAdjacencyUseAnchors(DM dm, PetscBool useAnchors)
70d71ae5a4SJacob Faibussowitsch {
718b0b4c70SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data;
728b0b4c70SToby Isaac
738b0b4c70SToby Isaac PetscFunctionBegin;
748b0b4c70SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
755b317d89SToby Isaac mesh->useAnchors = useAnchors;
763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
778b0b4c70SToby Isaac }
788b0b4c70SToby Isaac
798b0b4c70SToby Isaac /*@
80a17985deSToby Isaac DMPlexGetAdjacencyUseAnchors - Query whether adjacency in the mesh uses the point-to-point constraints.
818b0b4c70SToby Isaac
828b0b4c70SToby Isaac Input Parameter:
8320f4b53cSBarry Smith . dm - The `DM` object
848b0b4c70SToby Isaac
858b0b4c70SToby Isaac Output Parameter:
865b317d89SToby 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.
878b0b4c70SToby Isaac
888b0b4c70SToby Isaac Level: intermediate
898b0b4c70SToby Isaac
9020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexSetAdjacencyUseAnchors()`, `DMSetAdjacency()`, `DMGetAdjacency()`, `DMPlexDistribute()`, `DMPlexPreallocateOperator()`, `DMPlexSetAnchors()`
918b0b4c70SToby Isaac @*/
DMPlexGetAdjacencyUseAnchors(DM dm,PetscBool * useAnchors)92d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAdjacencyUseAnchors(DM dm, PetscBool *useAnchors)
93d71ae5a4SJacob Faibussowitsch {
948b0b4c70SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data;
958b0b4c70SToby Isaac
968b0b4c70SToby Isaac PetscFunctionBegin;
978b0b4c70SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
984f572ea9SToby Isaac PetscAssertPointer(useAnchors, 2);
995b317d89SToby Isaac *useAnchors = mesh->useAnchors;
1003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1018b0b4c70SToby Isaac }
1028b0b4c70SToby Isaac
DMPlexGetAdjacency_Cone_Internal(DM dm,PetscInt p,PetscInt * adjSize,PetscInt adj[])103d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetAdjacency_Cone_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[])
104d71ae5a4SJacob Faibussowitsch {
10570034214SMatthew G. Knepley const PetscInt *cone = NULL;
10670034214SMatthew G. Knepley PetscInt numAdj = 0, maxAdjSize = *adjSize, coneSize, c;
10770034214SMatthew G. Knepley
10870034214SMatthew G. Knepley PetscFunctionBeginHot;
1099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone));
1114b6b44bdSMatthew G. Knepley for (c = 0; c <= coneSize; ++c) {
1124b6b44bdSMatthew G. Knepley const PetscInt point = !c ? p : cone[c - 1];
11370034214SMatthew G. Knepley const PetscInt *support = NULL;
11470034214SMatthew G. Knepley PetscInt supportSize, s, q;
11570034214SMatthew G. Knepley
1169566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, point, &supportSize));
1179566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, point, &support));
11870034214SMatthew G. Knepley for (s = 0; s < supportSize; ++s) {
119527e7439SSatish Balay for (q = 0; q < numAdj || ((void)(adj[numAdj++] = support[s]), 0); ++q) {
12070034214SMatthew G. Knepley if (support[s] == adj[q]) break;
12170034214SMatthew G. Knepley }
12263a3b9bcSJacob Faibussowitsch PetscCheck(numAdj <= maxAdjSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%" PetscInt_FMT ")", maxAdjSize);
12370034214SMatthew G. Knepley }
12470034214SMatthew G. Knepley }
12570034214SMatthew G. Knepley *adjSize = numAdj;
1263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
12770034214SMatthew G. Knepley }
12870034214SMatthew G. Knepley
DMPlexGetAdjacency_Support_Internal(DM dm,PetscInt p,PetscInt * adjSize,PetscInt adj[])129d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetAdjacency_Support_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[])
130d71ae5a4SJacob Faibussowitsch {
13170034214SMatthew G. Knepley const PetscInt *support = NULL;
13270034214SMatthew G. Knepley PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s;
13370034214SMatthew G. Knepley
13470034214SMatthew G. Knepley PetscFunctionBeginHot;
1359566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
1369566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support));
1374b6b44bdSMatthew G. Knepley for (s = 0; s <= supportSize; ++s) {
1384b6b44bdSMatthew G. Knepley const PetscInt point = !s ? p : support[s - 1];
13970034214SMatthew G. Knepley const PetscInt *cone = NULL;
14070034214SMatthew G. Knepley PetscInt coneSize, c, q;
14170034214SMatthew G. Knepley
1429566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
1439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone));
14470034214SMatthew G. Knepley for (c = 0; c < coneSize; ++c) {
145527e7439SSatish Balay for (q = 0; q < numAdj || ((void)(adj[numAdj++] = cone[c]), 0); ++q) {
14670034214SMatthew G. Knepley if (cone[c] == adj[q]) break;
14770034214SMatthew G. Knepley }
14863a3b9bcSJacob Faibussowitsch PetscCheck(numAdj <= maxAdjSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%" PetscInt_FMT ")", maxAdjSize);
14970034214SMatthew G. Knepley }
15070034214SMatthew G. Knepley }
15170034214SMatthew G. Knepley *adjSize = numAdj;
1523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
15370034214SMatthew G. Knepley }
15470034214SMatthew G. Knepley
DMPlexGetAdjacency_Transitive_Internal(DM dm,PetscInt p,PetscBool useClosure,PetscInt * adjSize,PetscInt adj[])155d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetAdjacency_Transitive_Internal(DM dm, PetscInt p, PetscBool useClosure, PetscInt *adjSize, PetscInt adj[])
156d71ae5a4SJacob Faibussowitsch {
15770034214SMatthew G. Knepley PetscInt *star = NULL;
15870034214SMatthew G. Knepley PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s;
15970034214SMatthew G. Knepley
16070034214SMatthew G. Knepley PetscFunctionBeginHot;
1619566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, &star));
16270034214SMatthew G. Knepley for (s = 0; s < starSize * 2; s += 2) {
16370034214SMatthew G. Knepley const PetscInt *closure = NULL;
16470034214SMatthew G. Knepley PetscInt closureSize, c, q;
16570034214SMatthew G. Knepley
1669566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **)&closure));
16770034214SMatthew G. Knepley for (c = 0; c < closureSize * 2; c += 2) {
168527e7439SSatish Balay for (q = 0; q < numAdj || ((void)(adj[numAdj++] = closure[c]), 0); ++q) {
16970034214SMatthew G. Knepley if (closure[c] == adj[q]) break;
17070034214SMatthew G. Knepley }
17163a3b9bcSJacob Faibussowitsch PetscCheck(numAdj <= maxAdjSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%" PetscInt_FMT ")", maxAdjSize);
17270034214SMatthew G. Knepley }
1739566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **)&closure));
17470034214SMatthew G. Knepley }
1759566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, useClosure, &starSize, &star));
17670034214SMatthew G. Knepley *adjSize = numAdj;
1773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
17870034214SMatthew G. Knepley }
17970034214SMatthew G. Knepley
1808c5add6aSPierre Jolivet // Returns the maximum number of adjacent points in the DMPlex
DMPlexGetMaxAdjacencySize_Internal(DM dm,PetscBool useAnchors,PetscInt * max_adjacency_size)18116bce5ddSJames Wright PetscErrorCode DMPlexGetMaxAdjacencySize_Internal(DM dm, PetscBool useAnchors, PetscInt *max_adjacency_size)
182d71ae5a4SJacob Faibussowitsch {
18316bce5ddSJames Wright PetscInt depth, maxC, maxS, maxP, pStart, pEnd, asiz, maxAnchors = 1;
18416bce5ddSJames Wright
18516bce5ddSJames Wright PetscFunctionBeginUser;
18616bce5ddSJames Wright if (useAnchors) {
1878b0b4c70SToby Isaac PetscSection aSec = NULL;
1888b0b4c70SToby Isaac IS aIS = NULL;
18916bce5ddSJames Wright PetscInt aStart, aEnd;
1909566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
1918b0b4c70SToby Isaac if (aSec) {
1929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchors));
19324c766afSToby Isaac maxAnchors = PetscMax(1, maxAnchors);
1949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
1958b0b4c70SToby Isaac }
1968b0b4c70SToby Isaac }
19779bad331SMatthew G. Knepley
1989566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
1999566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
200412e9a14SMatthew G. Knepley depth = PetscMax(depth, -depth);
2019566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxC, &maxS));
202cf910586SMatthew G. Knepley maxP = maxS * maxC;
203cf910586SMatthew G. Knepley /* Adjacency can be as large as supp(cl(cell)) or cl(supp(vertex)),
204cf910586SMatthew G. Knepley supp(cell) + supp(maxC faces) + supp(maxC^2 edges) + supp(maxC^3 vertices)
205cf910586SMatthew G. Knepley = 0 + maxS*maxC + maxS^2*maxC^2 + maxS^3*maxC^3
206cf910586SMatthew G. Knepley = \sum^d_{i=0} (maxS*maxC)^i - 1
207cf910586SMatthew G. Knepley = (maxS*maxC)^{d+1} - 1 / (maxS*maxC - 1) - 1
208cf910586SMatthew G. Knepley We could improve this by getting the max by strata:
209cf910586SMatthew G. Knepley supp[d](cell) + supp[d-1](maxC[d] faces) + supp[1](maxC[d]*maxC[d-1] edges) + supp[0](maxC[d]*maxC[d-1]*maxC[d-2] vertices)
210cf910586SMatthew G. Knepley = 0 + maxS[d-1]*maxC[d] + maxS[1]*maxC[d]*maxC[d-1] + maxS[0]*maxC[d]*maxC[d-1]*maxC[d-2]
211cf910586SMatthew G. Knepley and the same with S and C reversed
212cf910586SMatthew G. Knepley */
213cf910586SMatthew G. Knepley if ((depth == 3 && maxP > 200) || (depth == 2 && maxP > 580)) asiz = pEnd - pStart;
214cf910586SMatthew G. Knepley else asiz = (maxP > 1) ? ((PetscPowInt(maxP, depth + 1) - 1) / (maxP - 1)) : depth + 1;
2158b0b4c70SToby Isaac asiz *= maxAnchors;
21616bce5ddSJames Wright *max_adjacency_size = PetscMin(asiz, pEnd - pStart);
21716bce5ddSJames Wright PetscFunctionReturn(PETSC_SUCCESS);
21816bce5ddSJames Wright }
21916bce5ddSJames Wright
22016bce5ddSJames Wright // Returns Adjacent mesh points to the selected point given specific criteria
22116bce5ddSJames Wright //
22216bce5ddSJames Wright // + adjSize - Number of adjacent points
22316bce5ddSJames Wright // - adj - Array of the adjacent points
DMPlexGetAdjacency_Internal(DM dm,PetscInt p,PetscBool useCone,PetscBool useTransitiveClosure,PetscBool useAnchors,PetscInt * adjSize,PetscInt * adj[])22416bce5ddSJames Wright PetscErrorCode DMPlexGetAdjacency_Internal(DM dm, PetscInt p, PetscBool useCone, PetscBool useTransitiveClosure, PetscBool useAnchors, PetscInt *adjSize, PetscInt *adj[])
22516bce5ddSJames Wright {
22616bce5ddSJames Wright static PetscInt asiz = 0;
22716bce5ddSJames Wright PetscInt aStart = -1, aEnd = -1;
22816bce5ddSJames Wright PetscInt maxAdjSize;
22916bce5ddSJames Wright PetscSection aSec = NULL;
23016bce5ddSJames Wright IS aIS = NULL;
23116bce5ddSJames Wright const PetscInt *anchors;
23216bce5ddSJames Wright DM_Plex *mesh = (DM_Plex *)dm->data;
23316bce5ddSJames Wright
23416bce5ddSJames Wright PetscFunctionBeginHot;
23516bce5ddSJames Wright if (useAnchors) {
23616bce5ddSJames Wright PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
23716bce5ddSJames Wright if (aSec) {
23816bce5ddSJames Wright PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
23916bce5ddSJames Wright PetscCall(ISGetIndices(aIS, &anchors));
24016bce5ddSJames Wright }
24116bce5ddSJames Wright }
24216bce5ddSJames Wright if (!*adj) {
24316bce5ddSJames Wright PetscCall(DMPlexGetMaxAdjacencySize_Internal(dm, useAnchors, &asiz));
2449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(asiz, adj));
24579bad331SMatthew G. Knepley }
24679bad331SMatthew G. Knepley if (*adjSize < 0) *adjSize = asiz;
2478b0b4c70SToby Isaac maxAdjSize = *adjSize;
2483c1f0c11SLawrence Mitchell if (mesh->useradjacency) {
2499566063dSJacob Faibussowitsch PetscCall((*mesh->useradjacency)(dm, p, adjSize, *adj, mesh->useradjacencyctx));
2503c1f0c11SLawrence Mitchell } else if (useTransitiveClosure) {
2519566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Transitive_Internal(dm, p, useCone, adjSize, *adj));
25270034214SMatthew G. Knepley } else if (useCone) {
2539566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Cone_Internal(dm, p, adjSize, *adj));
25470034214SMatthew G. Knepley } else {
2559566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Support_Internal(dm, p, adjSize, *adj));
25670034214SMatthew G. Knepley }
2575b317d89SToby Isaac if (useAnchors && aSec) {
2588b0b4c70SToby Isaac PetscInt origSize = *adjSize;
2598b0b4c70SToby Isaac PetscInt numAdj = origSize;
2608b0b4c70SToby Isaac PetscInt i = 0, j;
2618b0b4c70SToby Isaac PetscInt *orig = *adj;
2628b0b4c70SToby Isaac
2638b0b4c70SToby Isaac while (i < origSize) {
2648b0b4c70SToby Isaac PetscInt p = orig[i];
2658b0b4c70SToby Isaac PetscInt aDof = 0;
2668b0b4c70SToby Isaac
26748a46eb9SPierre Jolivet if (p >= aStart && p < aEnd) PetscCall(PetscSectionGetDof(aSec, p, &aDof));
2688b0b4c70SToby Isaac if (aDof) {
2698b0b4c70SToby Isaac PetscInt aOff;
2708b0b4c70SToby Isaac PetscInt s, q;
2718b0b4c70SToby Isaac
272ad540459SPierre Jolivet for (j = i + 1; j < numAdj; j++) orig[j - 1] = orig[j];
2738b0b4c70SToby Isaac origSize--;
2748b0b4c70SToby Isaac numAdj--;
2759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff));
2768b0b4c70SToby Isaac for (s = 0; s < aDof; ++s) {
277527e7439SSatish Balay for (q = 0; q < numAdj || ((void)(orig[numAdj++] = anchors[aOff + s]), 0); ++q) {
2788b0b4c70SToby Isaac if (anchors[aOff + s] == orig[q]) break;
2798b0b4c70SToby Isaac }
28063a3b9bcSJacob Faibussowitsch PetscCheck(numAdj <= maxAdjSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%" PetscInt_FMT ")", maxAdjSize);
2818b0b4c70SToby Isaac }
2829371c9d4SSatish Balay } else {
2838b0b4c70SToby Isaac i++;
2848b0b4c70SToby Isaac }
2858b0b4c70SToby Isaac }
2868b0b4c70SToby Isaac *adjSize = numAdj;
2879566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors));
2888b0b4c70SToby Isaac }
2893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
29070034214SMatthew G. Knepley }
29170034214SMatthew G. Knepley
29270034214SMatthew G. Knepley /*@
29370034214SMatthew G. Knepley DMPlexGetAdjacency - Return all points adjacent to the given point
29470034214SMatthew G. Knepley
29570034214SMatthew G. Knepley Input Parameters:
29620f4b53cSBarry Smith + dm - The `DM` object
2976b867d5aSJose E. Roman - p - The point
29870034214SMatthew G. Knepley
2996b867d5aSJose E. Roman Input/Output Parameters:
30020f4b53cSBarry Smith + adjSize - The maximum size of `adj` if it is non-`NULL`, or `PETSC_DETERMINE`;
3016b867d5aSJose E. Roman on output the number of adjacent points
30220f4b53cSBarry Smith - adj - Either `NULL` so that the array is allocated, or an existing array with size `adjSize`;
3036b867d5aSJose E. Roman on output contains the adjacent points
30470034214SMatthew G. Knepley
30570034214SMatthew G. Knepley Level: advanced
30670034214SMatthew G. Knepley
30795452b02SPatrick Sanan Notes:
30820f4b53cSBarry Smith The user must `PetscFree()` the `adj` array if it was not passed in.
30970034214SMatthew G. Knepley
31020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMCreateMatrix()`, `DMPlexPreallocateOperator()`
31170034214SMatthew G. Knepley @*/
DMPlexGetAdjacency(DM dm,PetscInt p,PetscInt * adjSize,PetscInt * adj[])312d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAdjacency(DM dm, PetscInt p, PetscInt *adjSize, PetscInt *adj[])
313d71ae5a4SJacob Faibussowitsch {
3141cf84007SMatthew G. Knepley PetscBool useCone, useClosure, useAnchors;
31570034214SMatthew G. Knepley
31670034214SMatthew G. Knepley PetscFunctionBeginHot;
31770034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3184f572ea9SToby Isaac PetscAssertPointer(adjSize, 3);
3194f572ea9SToby Isaac PetscAssertPointer(adj, 4);
3209566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure));
3219566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors));
3229566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, adjSize, adj));
3233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
32470034214SMatthew G. Knepley }
32508633170SToby Isaac
326b0a623aaSMatthew G. Knepley /*@
32720f4b53cSBarry Smith DMPlexCreateTwoSidedProcessSF - Create an `PetscSF` which just has process connectivity
328b0a623aaSMatthew G. Knepley
32920f4b53cSBarry Smith Collective
330b0a623aaSMatthew G. Knepley
331b0a623aaSMatthew G. Knepley Input Parameters:
33220f4b53cSBarry Smith + dm - The `DM`
33320f4b53cSBarry Smith . sfPoint - The `PetscSF` which encodes point connectivity
33420f4b53cSBarry Smith . rootRankSection - to be documented
33520f4b53cSBarry Smith . rootRanks - to be documented
33660225df5SJacob Faibussowitsch . leafRankSection - to be documented
33720f4b53cSBarry Smith - leafRanks - to be documented
338b0a623aaSMatthew G. Knepley
339b0a623aaSMatthew G. Knepley Output Parameters:
34020f4b53cSBarry Smith + processRanks - A list of process neighbors, or `NULL`
34120f4b53cSBarry Smith - sfProcess - An `PetscSF` encoding the two-sided process connectivity, or `NULL`
342b0a623aaSMatthew G. Knepley
343b0a623aaSMatthew G. Knepley Level: developer
344b0a623aaSMatthew G. Knepley
34520f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSFCreate()`, `DMPlexCreateProcessSF()`
346b0a623aaSMatthew G. Knepley @*/
DMPlexCreateTwoSidedProcessSF(DM dm,PetscSF sfPoint,PetscSection rootRankSection,IS rootRanks,PetscSection leafRankSection,IS leafRanks,PeOp IS * processRanks,PeOp PetscSF * sfProcess)347ce78bad3SBarry Smith PetscErrorCode DMPlexCreateTwoSidedProcessSF(DM dm, PetscSF sfPoint, PetscSection rootRankSection, IS rootRanks, PetscSection leafRankSection, IS leafRanks, PeOp IS *processRanks, PeOp PetscSF *sfProcess)
348d71ae5a4SJacob Faibussowitsch {
349b0a623aaSMatthew G. Knepley const PetscSFNode *remotePoints;
350b0a623aaSMatthew G. Knepley PetscInt *localPointsNew;
351b0a623aaSMatthew G. Knepley PetscSFNode *remotePointsNew;
352b0a623aaSMatthew G. Knepley const PetscInt *nranks;
353b0a623aaSMatthew G. Knepley PetscInt *ranksNew;
354b0a623aaSMatthew G. Knepley PetscBT neighbors;
355b0a623aaSMatthew G. Knepley PetscInt pStart, pEnd, p, numLeaves, l, numNeighbors, n;
3569852e123SBarry Smith PetscMPIInt size, proc, rank;
357b0a623aaSMatthew G. Knepley
358b0a623aaSMatthew G. Knepley PetscFunctionBegin;
359b0a623aaSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
360b0a623aaSMatthew G. Knepley PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2);
3614f572ea9SToby Isaac if (processRanks) PetscAssertPointer(processRanks, 7);
3624f572ea9SToby Isaac if (sfProcess) PetscAssertPointer(sfProcess, 8);
3639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
3649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
3659566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &numLeaves, NULL, &remotePoints));
3669566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(size, &neighbors));
3679566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(size, neighbors));
368b0a623aaSMatthew G. Knepley /* Compute root-to-leaf process connectivity */
3699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(rootRankSection, &pStart, &pEnd));
3709566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rootRanks, &nranks));
371b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) {
372b0a623aaSMatthew G. Knepley PetscInt ndof, noff, n;
373b0a623aaSMatthew G. Knepley
3749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootRankSection, p, &ndof));
3759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootRankSection, p, &noff));
3769566063dSJacob Faibussowitsch for (n = 0; n < ndof; ++n) PetscCall(PetscBTSet(neighbors, nranks[noff + n]));
377b0a623aaSMatthew G. Knepley }
3789566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rootRanks, &nranks));
379b0a623aaSMatthew G. Knepley /* Compute leaf-to-neighbor process connectivity */
3809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafRankSection, &pStart, &pEnd));
3819566063dSJacob Faibussowitsch PetscCall(ISGetIndices(leafRanks, &nranks));
382b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) {
383b0a623aaSMatthew G. Knepley PetscInt ndof, noff, n;
384b0a623aaSMatthew G. Knepley
3859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafRankSection, p, &ndof));
3869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafRankSection, p, &noff));
3879566063dSJacob Faibussowitsch for (n = 0; n < ndof; ++n) PetscCall(PetscBTSet(neighbors, nranks[noff + n]));
388b0a623aaSMatthew G. Knepley }
3899566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(leafRanks, &nranks));
390b0a623aaSMatthew G. Knepley /* Compute leaf-to-root process connectivity */
3913ba16761SJacob Faibussowitsch for (l = 0; l < numLeaves; ++l) PetscCall(PetscBTSet(neighbors, remotePoints[l].rank));
392b0a623aaSMatthew G. Knepley /* Calculate edges */
3933ba16761SJacob Faibussowitsch PetscCall(PetscBTClear(neighbors, rank));
3949371c9d4SSatish Balay for (proc = 0, numNeighbors = 0; proc < size; ++proc) {
3959371c9d4SSatish Balay if (PetscBTLookup(neighbors, proc)) ++numNeighbors;
3969371c9d4SSatish Balay }
3979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNeighbors, &ranksNew));
3989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNeighbors, &localPointsNew));
3999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNeighbors, &remotePointsNew));
4009852e123SBarry Smith for (proc = 0, n = 0; proc < size; ++proc) {
401b0a623aaSMatthew G. Knepley if (PetscBTLookup(neighbors, proc)) {
402b0a623aaSMatthew G. Knepley ranksNew[n] = proc;
403b0a623aaSMatthew G. Knepley localPointsNew[n] = proc;
404b0a623aaSMatthew G. Knepley remotePointsNew[n].index = rank;
405b0a623aaSMatthew G. Knepley remotePointsNew[n].rank = proc;
406b0a623aaSMatthew G. Knepley ++n;
407b0a623aaSMatthew G. Knepley }
408b0a623aaSMatthew G. Knepley }
4099566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&neighbors));
4109566063dSJacob Faibussowitsch if (processRanks) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), numNeighbors, ranksNew, PETSC_OWN_POINTER, processRanks));
4119566063dSJacob Faibussowitsch else PetscCall(PetscFree(ranksNew));
412b0a623aaSMatthew G. Knepley if (sfProcess) {
4139566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess));
4149566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*sfProcess, "Two-Sided Process SF"));
4159566063dSJacob Faibussowitsch PetscCall(PetscSFSetFromOptions(*sfProcess));
4169566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sfProcess, size, numNeighbors, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER));
417b0a623aaSMatthew G. Knepley }
4183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
419b0a623aaSMatthew G. Knepley }
420b0a623aaSMatthew G. Knepley
421b0a623aaSMatthew G. Knepley /*@
422b0a623aaSMatthew G. Knepley DMPlexDistributeOwnership - Compute owner information for shared points. This basically gets two-sided for an SF.
423b0a623aaSMatthew G. Knepley
42420f4b53cSBarry Smith Collective
425b0a623aaSMatthew G. Knepley
426b0a623aaSMatthew G. Knepley Input Parameter:
42720f4b53cSBarry Smith . dm - The `DM`
428b0a623aaSMatthew G. Knepley
429b0a623aaSMatthew G. Knepley Output Parameters:
430b0a623aaSMatthew G. Knepley + rootSection - The number of leaves for a given root point
431b0a623aaSMatthew G. Knepley . rootrank - The rank of each edge into the root point
432b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point
433b0a623aaSMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point
434b0a623aaSMatthew G. Knepley
435b0a623aaSMatthew G. Knepley Level: developer
436b0a623aaSMatthew G. Knepley
43720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabel()`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()`
438b0a623aaSMatthew G. Knepley @*/
DMPlexDistributeOwnership(DM dm,PetscSection rootSection,IS * rootrank,PetscSection leafSection,IS * leafrank)439d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeOwnership(DM dm, PetscSection rootSection, IS *rootrank, PetscSection leafSection, IS *leafrank)
440d71ae5a4SJacob Faibussowitsch {
441b0a623aaSMatthew G. Knepley MPI_Comm comm;
442b0a623aaSMatthew G. Knepley PetscSF sfPoint;
443b0a623aaSMatthew G. Knepley const PetscInt *rootdegree;
444b0a623aaSMatthew G. Knepley PetscInt *myrank, *remoterank;
445b0a623aaSMatthew G. Knepley PetscInt pStart, pEnd, p, nedges;
446b0a623aaSMatthew G. Knepley PetscMPIInt rank;
447b0a623aaSMatthew G. Knepley
448b0a623aaSMatthew G. Knepley PetscFunctionBegin;
4499566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
4519566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4529566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint));
453b0a623aaSMatthew G. Knepley /* Compute number of leaves for each root */
4549566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rootSection, "Root Section"));
4559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection, pStart, pEnd));
4569566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sfPoint, &rootdegree));
4579566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sfPoint, &rootdegree));
4589566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(rootSection, p, rootdegree[p - pStart]));
4599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection));
460b0a623aaSMatthew G. Knepley /* Gather rank of each leaf to root */
4619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &nedges));
4629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &myrank));
4639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nedges, &remoterank));
464b0a623aaSMatthew G. Knepley for (p = 0; p < pEnd - pStart; ++p) myrank[p] = rank;
4659566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sfPoint, MPIU_INT, myrank, remoterank));
4669566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sfPoint, MPIU_INT, myrank, remoterank));
4679566063dSJacob Faibussowitsch PetscCall(PetscFree(myrank));
4689566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, nedges, remoterank, PETSC_OWN_POINTER, rootrank));
469b0a623aaSMatthew G. Knepley /* Distribute remote ranks to leaves */
4709566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)leafSection, "Leaf Section"));
4719566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeFieldIS(dm, sfPoint, rootSection, *rootrank, leafSection, leafrank));
4723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
473b0a623aaSMatthew G. Knepley }
474b0a623aaSMatthew G. Knepley
475ce78bad3SBarry Smith /*@
476c506a872SMatthew G. Knepley DMPlexCreateOverlapLabel - Compute a label indicating what overlap points should be sent to new processes
477b0a623aaSMatthew G. Knepley
47820f4b53cSBarry Smith Collective
479b0a623aaSMatthew G. Knepley
480b0a623aaSMatthew G. Knepley Input Parameters:
48120f4b53cSBarry Smith + dm - The `DM`
48224d039d7SMichael Lange . levels - Number of overlap levels
483b0a623aaSMatthew G. Knepley . rootSection - The number of leaves for a given root point
484b0a623aaSMatthew G. Knepley . rootrank - The rank of each edge into the root point
485b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point
486b0a623aaSMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point
487b0a623aaSMatthew G. Knepley
488064ec1f3Sprj- Output Parameter:
48920f4b53cSBarry Smith . ovLabel - `DMLabel` containing remote overlap contributions as point/rank pairings
490b0a623aaSMatthew G. Knepley
491b0a623aaSMatthew G. Knepley Level: developer
492b0a623aaSMatthew G. Knepley
49320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabelFromLabels()`, `DMPlexGetAdjacency()`, `DMPlexDistributeOwnership()`, `DMPlexDistribute()`
494b0a623aaSMatthew G. Knepley @*/
DMPlexCreateOverlapLabel(DM dm,PetscInt levels,PetscSection rootSection,IS rootrank,PetscSection leafSection,IS leafrank,DMLabel * ovLabel)495d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateOverlapLabel(DM dm, PetscInt levels, PetscSection rootSection, IS rootrank, PetscSection leafSection, IS leafrank, DMLabel *ovLabel)
496d71ae5a4SJacob Faibussowitsch {
497e540f424SMichael Lange MPI_Comm comm;
498b0a623aaSMatthew G. Knepley DMLabel ovAdjByRank; /* A DMLabel containing all points adjacent to shared points, separated by rank (value in label) */
499874ddda9SLisandro Dalcin PetscSF sfPoint;
500b0a623aaSMatthew G. Knepley const PetscSFNode *remote;
501b0a623aaSMatthew G. Knepley const PetscInt *local;
5021fd9873aSMichael Lange const PetscInt *nrank, *rrank;
503b0a623aaSMatthew G. Knepley PetscInt *adj = NULL;
5041fd9873aSMichael Lange PetscInt pStart, pEnd, p, sStart, sEnd, nleaves, l;
5059852e123SBarry Smith PetscMPIInt rank, size;
50631bc6364SLisandro Dalcin PetscBool flg;
507b0a623aaSMatthew G. Knepley
508b0a623aaSMatthew G. Knepley PetscFunctionBegin;
5096ba1a4c7SVaclav Hapla *ovLabel = NULL;
5109566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
5129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
5133ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS);
5149566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint));
5159566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
516d1674c6dSMatthew Knepley if (!levels) {
517d1674c6dSMatthew Knepley /* Add owned points */
5189566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel));
5199566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) PetscCall(DMLabelSetValue(*ovLabel, p, rank));
5203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
521d1674c6dSMatthew Knepley }
5229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafSection, &sStart, &sEnd));
5239566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote));
5249566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap adjacency", &ovAdjByRank));
525b0a623aaSMatthew G. Knepley /* Handle leaves: shared with the root point */
526b0a623aaSMatthew G. Knepley for (l = 0; l < nleaves; ++l) {
527b0a623aaSMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a;
528b0a623aaSMatthew G. Knepley
5299566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, local ? local[l] : l, &adjSize, &adj));
5309566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remote[l].rank));
531b0a623aaSMatthew G. Knepley }
5329566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rootrank, &rrank));
5339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(leafrank, &nrank));
534b0a623aaSMatthew G. Knepley /* Handle roots */
535b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) {
536b0a623aaSMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, neighbors = 0, noff, n, a;
537b0a623aaSMatthew G. Knepley
538b0a623aaSMatthew G. Knepley if ((p >= sStart) && (p < sEnd)) {
539b0a623aaSMatthew G. Knepley /* Some leaves share a root with other leaves on different processes */
5409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, p, &neighbors));
541b0a623aaSMatthew G. Knepley if (neighbors) {
5429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafSection, p, &noff));
5439566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj));
544b0a623aaSMatthew G. Knepley for (n = 0; n < neighbors; ++n) {
545b0a623aaSMatthew G. Knepley const PetscInt remoteRank = nrank[noff + n];
546b0a623aaSMatthew G. Knepley
547b0a623aaSMatthew G. Knepley if (remoteRank == rank) continue;
5489566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank));
549b0a623aaSMatthew G. Knepley }
550b0a623aaSMatthew G. Knepley }
551b0a623aaSMatthew G. Knepley }
552b0a623aaSMatthew G. Knepley /* Roots are shared with leaves */
5539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSection, p, &neighbors));
554b0a623aaSMatthew G. Knepley if (!neighbors) continue;
5559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, p, &noff));
5569566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj));
557b0a623aaSMatthew G. Knepley for (n = 0; n < neighbors; ++n) {
558b0a623aaSMatthew G. Knepley const PetscInt remoteRank = rrank[noff + n];
559b0a623aaSMatthew G. Knepley
560b0a623aaSMatthew G. Knepley if (remoteRank == rank) continue;
5619566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank));
562b0a623aaSMatthew G. Knepley }
563b0a623aaSMatthew G. Knepley }
5649566063dSJacob Faibussowitsch PetscCall(PetscFree(adj));
5659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rootrank, &rrank));
5669566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(leafrank, &nrank));
56724d039d7SMichael Lange /* Add additional overlap levels */
568be200f8dSMichael Lange for (l = 1; l < levels; l++) {
569be200f8dSMichael Lange /* Propagate point donations over SF to capture remote connections */
5709566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelPropagate(dm, ovAdjByRank));
571be200f8dSMichael Lange /* Add next level of point donations to the label */
5729566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelAdjacency(dm, ovAdjByRank));
573be200f8dSMichael Lange }
57426a7d390SMatthew G. Knepley /* We require the closure in the overlap */
5759566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelClosure(dm, ovAdjByRank));
5769566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-overlap_view", &flg));
577e540f424SMichael Lange if (flg) {
578825f8a23SLisandro Dalcin PetscViewer viewer;
5799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &viewer));
5809566063dSJacob Faibussowitsch PetscCall(DMLabelView(ovAdjByRank, viewer));
581b0a623aaSMatthew G. Knepley }
582874ddda9SLisandro Dalcin /* Invert sender to receiver label */
5839566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel));
5849566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelInvert(dm, ovAdjByRank, NULL, *ovLabel));
585a9f1d5b2SMichael Lange /* Add owned points, except for shared local points */
5869566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) PetscCall(DMLabelSetValue(*ovLabel, p, rank));
587e540f424SMichael Lange for (l = 0; l < nleaves; ++l) {
5889566063dSJacob Faibussowitsch PetscCall(DMLabelClearValue(*ovLabel, local[l], rank));
5899566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(*ovLabel, remote[l].index, remote[l].rank));
590e540f424SMichael Lange }
591e540f424SMichael Lange /* Clean up */
5929566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&ovAdjByRank));
5933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
594b0a623aaSMatthew G. Knepley }
59570034214SMatthew G. Knepley
HandlePoint_Private(DM dm,PetscInt p,PetscSection section,const PetscInt ranks[],PetscInt numExLabels,const DMLabel exLabel[],const PetscInt exValue[],DMLabel ovAdjByRank)596d71ae5a4SJacob Faibussowitsch static PetscErrorCode HandlePoint_Private(DM dm, PetscInt p, PetscSection section, const PetscInt ranks[], PetscInt numExLabels, const DMLabel exLabel[], const PetscInt exValue[], DMLabel ovAdjByRank)
597d71ae5a4SJacob Faibussowitsch {
598c506a872SMatthew G. Knepley PetscInt neighbors, el;
599c506a872SMatthew G. Knepley
600c506a872SMatthew G. Knepley PetscFunctionBegin;
601c506a872SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, p, &neighbors));
602c506a872SMatthew G. Knepley if (neighbors) {
603c506a872SMatthew G. Knepley PetscInt *adj = NULL;
604c506a872SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, noff, n, a;
605c506a872SMatthew G. Knepley PetscMPIInt rank;
606c506a872SMatthew G. Knepley
607c506a872SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
608c506a872SMatthew G. Knepley PetscCall(PetscSectionGetOffset(section, p, &noff));
609c506a872SMatthew G. Knepley PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj));
610c506a872SMatthew G. Knepley for (n = 0; n < neighbors; ++n) {
611c506a872SMatthew G. Knepley const PetscInt remoteRank = ranks[noff + n];
612c506a872SMatthew G. Knepley
613c506a872SMatthew G. Knepley if (remoteRank == rank) continue;
614c506a872SMatthew G. Knepley for (a = 0; a < adjSize; ++a) {
615c506a872SMatthew G. Knepley PetscBool insert = PETSC_TRUE;
616c506a872SMatthew G. Knepley
617c506a872SMatthew G. Knepley for (el = 0; el < numExLabels; ++el) {
618c506a872SMatthew G. Knepley PetscInt exVal;
619c506a872SMatthew G. Knepley PetscCall(DMLabelGetValue(exLabel[el], adj[a], &exVal));
6209371c9d4SSatish Balay if (exVal == exValue[el]) {
6219371c9d4SSatish Balay insert = PETSC_FALSE;
6229371c9d4SSatish Balay break;
6239371c9d4SSatish Balay }
624c506a872SMatthew G. Knepley }
625c506a872SMatthew G. Knepley if (insert) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank));
626c506a872SMatthew G. Knepley }
627c506a872SMatthew G. Knepley }
628f88a03deSMatthew G. Knepley PetscCall(PetscFree(adj));
629c506a872SMatthew G. Knepley }
6303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
631c506a872SMatthew G. Knepley }
632c506a872SMatthew G. Knepley
633c506a872SMatthew G. Knepley /*@C
634c506a872SMatthew G. Knepley DMPlexCreateOverlapLabelFromLabels - Compute a label indicating what overlap points should be sent to new processes
635c506a872SMatthew G. Knepley
63620f4b53cSBarry Smith Collective
637c506a872SMatthew G. Knepley
638c506a872SMatthew G. Knepley Input Parameters:
63920f4b53cSBarry Smith + dm - The `DM`
640c506a872SMatthew G. Knepley . numLabels - The number of labels to draw candidate points from
641c506a872SMatthew G. Knepley . label - An array of labels containing candidate points
642c506a872SMatthew G. Knepley . value - An array of label values marking the candidate points
643c506a872SMatthew G. Knepley . numExLabels - The number of labels to use for exclusion
64420f4b53cSBarry Smith . exLabel - An array of labels indicating points to be excluded, or `NULL`
64520f4b53cSBarry Smith . exValue - An array of label values to be excluded, or `NULL`
646c506a872SMatthew G. Knepley . rootSection - The number of leaves for a given root point
647c506a872SMatthew G. Knepley . rootrank - The rank of each edge into the root point
648c506a872SMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point
649c506a872SMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point
650c506a872SMatthew G. Knepley
651c506a872SMatthew G. Knepley Output Parameter:
65220f4b53cSBarry Smith . ovLabel - `DMLabel` containing remote overlap contributions as point/rank pairings
65320f4b53cSBarry Smith
65420f4b53cSBarry Smith Level: developer
655c506a872SMatthew G. Knepley
656c506a872SMatthew G. Knepley Note:
657c506a872SMatthew G. Knepley The candidate points are only added to the overlap if they are adjacent to a shared point
658c506a872SMatthew G. Knepley
65920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabel()`, `DMPlexGetAdjacency()`, `DMPlexDistributeOwnership()`, `DMPlexDistribute()`
660c506a872SMatthew G. Knepley @*/
DMPlexCreateOverlapLabelFromLabels(DM dm,PetscInt numLabels,const DMLabel label[],const PetscInt value[],PetscInt numExLabels,const DMLabel exLabel[],const PetscInt exValue[],PetscSection rootSection,IS rootrank,PetscSection leafSection,IS leafrank,DMLabel * ovLabel)661d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateOverlapLabelFromLabels(DM dm, PetscInt numLabels, const DMLabel label[], const PetscInt value[], PetscInt numExLabels, const DMLabel exLabel[], const PetscInt exValue[], PetscSection rootSection, IS rootrank, PetscSection leafSection, IS leafrank, DMLabel *ovLabel)
662d71ae5a4SJacob Faibussowitsch {
663c506a872SMatthew G. Knepley MPI_Comm comm;
664c506a872SMatthew G. Knepley DMLabel ovAdjByRank; /* A DMLabel containing all points adjacent to shared points, separated by rank (value in label) */
665c506a872SMatthew G. Knepley PetscSF sfPoint;
666c506a872SMatthew G. Knepley const PetscSFNode *remote;
667c506a872SMatthew G. Knepley const PetscInt *local;
668c506a872SMatthew G. Knepley const PetscInt *nrank, *rrank;
669c506a872SMatthew G. Knepley PetscInt *adj = NULL;
670c506a872SMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, nleaves, l, el;
671c506a872SMatthew G. Knepley PetscMPIInt rank, size;
672c506a872SMatthew G. Knepley PetscBool flg;
673c506a872SMatthew G. Knepley
674c506a872SMatthew G. Knepley PetscFunctionBegin;
675c506a872SMatthew G. Knepley *ovLabel = NULL;
676c506a872SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
677c506a872SMatthew G. Knepley PetscCallMPI(MPI_Comm_size(comm, &size));
678c506a872SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank));
6793ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS);
680c506a872SMatthew G. Knepley PetscCall(DMGetPointSF(dm, &sfPoint));
681c506a872SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
682c506a872SMatthew G. Knepley PetscCall(PetscSectionGetChart(leafSection, &sStart, &sEnd));
683c506a872SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote));
684c506a872SMatthew G. Knepley PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap adjacency", &ovAdjByRank));
685c506a872SMatthew G. Knepley PetscCall(ISGetIndices(rootrank, &rrank));
686c506a872SMatthew G. Knepley PetscCall(ISGetIndices(leafrank, &nrank));
687c506a872SMatthew G. Knepley for (l = 0; l < numLabels; ++l) {
688c506a872SMatthew G. Knepley IS valIS;
689c506a872SMatthew G. Knepley const PetscInt *points;
690c506a872SMatthew G. Knepley PetscInt n;
691c506a872SMatthew G. Knepley
692c506a872SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label[l], value[l], &valIS));
693c506a872SMatthew G. Knepley if (!valIS) continue;
694c506a872SMatthew G. Knepley PetscCall(ISGetIndices(valIS, &points));
695c506a872SMatthew G. Knepley PetscCall(ISGetLocalSize(valIS, &n));
696c506a872SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) {
697c506a872SMatthew G. Knepley const PetscInt p = points[i];
698c506a872SMatthew G. Knepley
699c506a872SMatthew G. Knepley if ((p >= sStart) && (p < sEnd)) {
700c506a872SMatthew G. Knepley PetscInt loc, adjSize = PETSC_DETERMINE;
701c506a872SMatthew G. Knepley
702c506a872SMatthew G. Knepley /* Handle leaves: shared with the root point */
703c506a872SMatthew G. Knepley if (local) PetscCall(PetscFindInt(p, nleaves, local, &loc));
704c506a872SMatthew G. Knepley else loc = (p >= 0 && p < nleaves) ? p : -1;
705c506a872SMatthew G. Knepley if (loc >= 0) {
706c506a872SMatthew G. Knepley const PetscInt remoteRank = remote[loc].rank;
707c506a872SMatthew G. Knepley
708c506a872SMatthew G. Knepley PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj));
709c506a872SMatthew G. Knepley for (PetscInt a = 0; a < adjSize; ++a) {
710c506a872SMatthew G. Knepley PetscBool insert = PETSC_TRUE;
711c506a872SMatthew G. Knepley
712c506a872SMatthew G. Knepley for (el = 0; el < numExLabels; ++el) {
713c506a872SMatthew G. Knepley PetscInt exVal;
714c506a872SMatthew G. Knepley PetscCall(DMLabelGetValue(exLabel[el], adj[a], &exVal));
7159371c9d4SSatish Balay if (exVal == exValue[el]) {
7169371c9d4SSatish Balay insert = PETSC_FALSE;
7179371c9d4SSatish Balay break;
7189371c9d4SSatish Balay }
719c506a872SMatthew G. Knepley }
720c506a872SMatthew G. Knepley if (insert) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank));
721c506a872SMatthew G. Knepley }
722c506a872SMatthew G. Knepley }
723c506a872SMatthew G. Knepley /* Some leaves share a root with other leaves on different processes */
7243ba16761SJacob Faibussowitsch PetscCall(HandlePoint_Private(dm, p, leafSection, nrank, numExLabels, exLabel, exValue, ovAdjByRank));
725c506a872SMatthew G. Knepley }
726c506a872SMatthew G. Knepley /* Roots are shared with leaves */
7273ba16761SJacob Faibussowitsch PetscCall(HandlePoint_Private(dm, p, rootSection, rrank, numExLabels, exLabel, exValue, ovAdjByRank));
728c506a872SMatthew G. Knepley }
729c506a872SMatthew G. Knepley PetscCall(ISRestoreIndices(valIS, &points));
730c506a872SMatthew G. Knepley PetscCall(ISDestroy(&valIS));
731c506a872SMatthew G. Knepley }
732c506a872SMatthew G. Knepley PetscCall(PetscFree(adj));
733c506a872SMatthew G. Knepley PetscCall(ISRestoreIndices(rootrank, &rrank));
734c506a872SMatthew G. Knepley PetscCall(ISRestoreIndices(leafrank, &nrank));
735c506a872SMatthew G. Knepley /* We require the closure in the overlap */
736c506a872SMatthew G. Knepley PetscCall(DMPlexPartitionLabelClosure(dm, ovAdjByRank));
737c506a872SMatthew G. Knepley PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-overlap_view", &flg));
738c506a872SMatthew G. Knepley if (flg) {
739c506a872SMatthew G. Knepley PetscViewer viewer;
740c506a872SMatthew G. Knepley PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &viewer));
741c506a872SMatthew G. Knepley PetscCall(DMLabelView(ovAdjByRank, viewer));
742c506a872SMatthew G. Knepley }
743c506a872SMatthew G. Knepley /* Invert sender to receiver label */
744c506a872SMatthew G. Knepley PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel));
745c506a872SMatthew G. Knepley PetscCall(DMPlexPartitionLabelInvert(dm, ovAdjByRank, NULL, *ovLabel));
746c506a872SMatthew G. Knepley /* Add owned points, except for shared local points */
747c506a872SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) PetscCall(DMLabelSetValue(*ovLabel, p, rank));
748c506a872SMatthew G. Knepley for (l = 0; l < nleaves; ++l) {
749c506a872SMatthew G. Knepley PetscCall(DMLabelClearValue(*ovLabel, local[l], rank));
750c506a872SMatthew G. Knepley PetscCall(DMLabelSetValue(*ovLabel, remote[l].index, remote[l].rank));
751c506a872SMatthew G. Knepley }
752c506a872SMatthew G. Knepley /* Clean up */
753c506a872SMatthew G. Knepley PetscCall(DMLabelDestroy(&ovAdjByRank));
7543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
755c506a872SMatthew G. Knepley }
756c506a872SMatthew G. Knepley
757cc4c1da9SBarry Smith /*@
75820f4b53cSBarry Smith DMPlexCreateOverlapMigrationSF - Create a `PetscSF` describing the new mesh distribution to make the overlap described by the input `PetscSF`
75924cc2ca5SMatthew G. Knepley
76020f4b53cSBarry Smith Collective
76124cc2ca5SMatthew G. Knepley
76224cc2ca5SMatthew G. Knepley Input Parameters:
76320f4b53cSBarry Smith + dm - The `DM`
76420f4b53cSBarry Smith - overlapSF - The `PetscSF` mapping ghost points in overlap to owner points on other processes
76524cc2ca5SMatthew G. Knepley
766064ec1f3Sprj- Output Parameter:
76720f4b53cSBarry Smith . migrationSF - A `PetscSF` that maps original points in old locations to points in new locations
76824cc2ca5SMatthew G. Knepley
76924cc2ca5SMatthew G. Knepley Level: developer
77024cc2ca5SMatthew G. Knepley
77120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabel()`, `DMPlexDistributeOverlap()`, `DMPlexDistribute()`
77224cc2ca5SMatthew G. Knepley @*/
DMPlexCreateOverlapMigrationSF(DM dm,PetscSF overlapSF,PetscSF * migrationSF)773d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateOverlapMigrationSF(DM dm, PetscSF overlapSF, PetscSF *migrationSF)
774d71ae5a4SJacob Faibussowitsch {
77546f9b1c3SMichael Lange MPI_Comm comm;
7769852e123SBarry Smith PetscMPIInt rank, size;
77746f9b1c3SMichael Lange PetscInt d, dim, p, pStart, pEnd, nroots, nleaves, newLeaves, point, numSharedPoints;
77846f9b1c3SMichael Lange PetscInt *pointDepths, *remoteDepths, *ilocal;
77946f9b1c3SMichael Lange PetscInt *depthRecv, *depthShift, *depthIdx;
78046f9b1c3SMichael Lange PetscSFNode *iremote;
78146f9b1c3SMichael Lange PetscSF pointSF;
78246f9b1c3SMichael Lange const PetscInt *sharedLocal;
78346f9b1c3SMichael Lange const PetscSFNode *overlapRemote, *sharedRemote;
78446f9b1c3SMichael Lange
78546f9b1c3SMichael Lange PetscFunctionBegin;
78646f9b1c3SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7879566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
7889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
7899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
7909566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
79146f9b1c3SMichael Lange
79246f9b1c3SMichael Lange /* Before building the migration SF we need to know the new stratum offsets */
7939566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(overlapSF, &nroots, &nleaves, NULL, &overlapRemote));
7949566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths));
79546f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) {
7969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
79746f9b1c3SMichael Lange for (p = pStart; p < pEnd; p++) pointDepths[p] = d;
79846f9b1c3SMichael Lange }
79946f9b1c3SMichael Lange for (p = 0; p < nleaves; p++) remoteDepths[p] = -1;
8009566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(overlapSF, MPIU_INT, pointDepths, remoteDepths, MPI_REPLACE));
8019566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(overlapSF, MPIU_INT, pointDepths, remoteDepths, MPI_REPLACE));
80246f9b1c3SMichael Lange
8032d4ee042Sprj- /* Count received points in each stratum and compute the internal strata shift */
8049566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim + 1, &depthRecv, dim + 1, &depthShift, dim + 1, &depthIdx));
80546f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) depthRecv[d] = 0;
80646f9b1c3SMichael Lange for (p = 0; p < nleaves; p++) depthRecv[remoteDepths[p]]++;
80746f9b1c3SMichael Lange depthShift[dim] = 0;
80846f9b1c3SMichael Lange for (d = 0; d < dim; d++) depthShift[d] = depthRecv[dim];
80946f9b1c3SMichael Lange for (d = 1; d < dim; d++) depthShift[d] += depthRecv[0];
81046f9b1c3SMichael Lange for (d = dim - 2; d > 0; d--) depthShift[d] += depthRecv[d + 1];
81146f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) {
8129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
81346f9b1c3SMichael Lange depthIdx[d] = pStart + depthShift[d];
81446f9b1c3SMichael Lange }
81546f9b1c3SMichael Lange
81646f9b1c3SMichael Lange /* Form the overlap SF build an SF that describes the full overlap migration SF */
8179566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
81846f9b1c3SMichael Lange newLeaves = pEnd - pStart + nleaves;
8199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newLeaves, &ilocal));
8209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newLeaves, &iremote));
82146f9b1c3SMichael Lange /* First map local points to themselves */
82246f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) {
8239566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
82446f9b1c3SMichael Lange for (p = pStart; p < pEnd; p++) {
82546f9b1c3SMichael Lange point = p + depthShift[d];
82646f9b1c3SMichael Lange ilocal[point] = point;
82746f9b1c3SMichael Lange iremote[point].index = p;
82846f9b1c3SMichael Lange iremote[point].rank = rank;
82946f9b1c3SMichael Lange depthIdx[d]++;
83046f9b1c3SMichael Lange }
83146f9b1c3SMichael Lange }
83246f9b1c3SMichael Lange
83346f9b1c3SMichael Lange /* Add in the remote roots for currently shared points */
8349566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &pointSF));
8359566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, NULL, &numSharedPoints, &sharedLocal, &sharedRemote));
83646f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) {
8379566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
83846f9b1c3SMichael Lange for (p = 0; p < numSharedPoints; p++) {
83946f9b1c3SMichael Lange if (pStart <= sharedLocal[p] && sharedLocal[p] < pEnd) {
84046f9b1c3SMichael Lange point = sharedLocal[p] + depthShift[d];
84146f9b1c3SMichael Lange iremote[point].index = sharedRemote[p].index;
84246f9b1c3SMichael Lange iremote[point].rank = sharedRemote[p].rank;
84346f9b1c3SMichael Lange }
84446f9b1c3SMichael Lange }
84546f9b1c3SMichael Lange }
84646f9b1c3SMichael Lange
84746f9b1c3SMichael Lange /* Now add the incoming overlap points */
84846f9b1c3SMichael Lange for (p = 0; p < nleaves; p++) {
84946f9b1c3SMichael Lange point = depthIdx[remoteDepths[p]];
85046f9b1c3SMichael Lange ilocal[point] = point;
85146f9b1c3SMichael Lange iremote[point].index = overlapRemote[p].index;
85246f9b1c3SMichael Lange iremote[point].rank = overlapRemote[p].rank;
85346f9b1c3SMichael Lange depthIdx[remoteDepths[p]]++;
85446f9b1c3SMichael Lange }
8559566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointDepths, remoteDepths));
85646f9b1c3SMichael Lange
8579566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, migrationSF));
8589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*migrationSF, "Overlap Migration SF"));
8599566063dSJacob Faibussowitsch PetscCall(PetscSFSetFromOptions(*migrationSF));
8609566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8619566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*migrationSF, pEnd - pStart, newLeaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER));
86246f9b1c3SMichael Lange
8639566063dSJacob Faibussowitsch PetscCall(PetscFree3(depthRecv, depthShift, depthIdx));
8643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
86570034214SMatthew G. Knepley }
86670034214SMatthew G. Knepley
867a9f1d5b2SMichael Lange /*@
868f0e73a3dSToby Isaac DMPlexStratifyMigrationSF - Rearrange the leaves of a migration sf for stratification.
869a9f1d5b2SMichael Lange
870064ec1f3Sprj- Input Parameters:
871a9f1d5b2SMichael Lange + dm - The DM
872a9f1d5b2SMichael Lange - sf - A star forest with non-ordered leaves, usually defining a DM point migration
873a9f1d5b2SMichael Lange
874a9f1d5b2SMichael Lange Output Parameter:
875a9f1d5b2SMichael Lange . migrationSF - A star forest with added leaf indirection that ensures the resulting DM is stratified
876a9f1d5b2SMichael Lange
87720f4b53cSBarry Smith Level: developer
87820f4b53cSBarry Smith
879412e9a14SMatthew G. Knepley Note:
880412e9a14SMatthew G. Knepley This lexicographically sorts by (depth, cellType)
881412e9a14SMatthew G. Knepley
88220f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()`
883a9f1d5b2SMichael Lange @*/
DMPlexStratifyMigrationSF(DM dm,PetscSF sf,PetscSF * migrationSF)884d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratifyMigrationSF(DM dm, PetscSF sf, PetscSF *migrationSF)
885d71ae5a4SJacob Faibussowitsch {
886a9f1d5b2SMichael Lange MPI_Comm comm;
8879852e123SBarry Smith PetscMPIInt rank, size;
888412e9a14SMatthew G. Knepley PetscInt d, ldepth, depth, dim, p, pStart, pEnd, nroots, nleaves;
889412e9a14SMatthew G. Knepley PetscSFNode *pointDepths, *remoteDepths;
890412e9a14SMatthew G. Knepley PetscInt *ilocal;
891a9f1d5b2SMichael Lange PetscInt *depthRecv, *depthShift, *depthIdx;
892412e9a14SMatthew G. Knepley PetscInt *ctRecv, *ctShift, *ctIdx;
893a9f1d5b2SMichael Lange const PetscSFNode *iremote;
894a9f1d5b2SMichael Lange
895a9f1d5b2SMichael Lange PetscFunctionBegin;
896a9f1d5b2SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8979566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
8989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
8999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
9009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &ldepth));
9019566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
902462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&ldepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
90363a3b9bcSJacob Faibussowitsch PetscCheck(!(ldepth >= 0) || !(depth != ldepth), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %" PetscInt_FMT " != %" PetscInt_FMT, ldepth, depth);
9049566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartStratSF, dm, 0, 0, 0));
905a9f1d5b2SMichael Lange
906a9f1d5b2SMichael Lange /* Before building the migration SF we need to know the new stratum offsets */
9079566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, &iremote));
9089566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths));
9097fab53ddSMatthew G. Knepley for (d = 0; d < depth + 1; ++d) {
9109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
911f0e73a3dSToby Isaac for (p = pStart; p < pEnd; ++p) {
912412e9a14SMatthew G. Knepley DMPolytopeType ct;
913f0e73a3dSToby Isaac
9149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct));
915412e9a14SMatthew G. Knepley pointDepths[p].index = d;
916412e9a14SMatthew G. Knepley pointDepths[p].rank = ct;
917f0e73a3dSToby Isaac }
918412e9a14SMatthew G. Knepley }
9199371c9d4SSatish Balay for (p = 0; p < nleaves; ++p) {
9209371c9d4SSatish Balay remoteDepths[p].index = -1;
9219371c9d4SSatish Balay remoteDepths[p].rank = -1;
9229371c9d4SSatish Balay }
9236497c311SBarry Smith PetscCall(PetscSFBcastBegin(sf, MPIU_SF_NODE, pointDepths, remoteDepths, MPI_REPLACE));
9246497c311SBarry Smith PetscCall(PetscSFBcastEnd(sf, MPIU_SF_NODE, pointDepths, remoteDepths, MPI_REPLACE));
925412e9a14SMatthew G. Knepley /* Count received points in each stratum and compute the internal strata shift */
9269566063dSJacob Faibussowitsch PetscCall(PetscCalloc6(depth + 1, &depthRecv, depth + 1, &depthShift, depth + 1, &depthIdx, DM_NUM_POLYTOPES, &ctRecv, DM_NUM_POLYTOPES, &ctShift, DM_NUM_POLYTOPES, &ctIdx));
927412e9a14SMatthew G. Knepley for (p = 0; p < nleaves; ++p) {
928412e9a14SMatthew G. Knepley if (remoteDepths[p].rank < 0) {
929412e9a14SMatthew G. Knepley ++depthRecv[remoteDepths[p].index];
930412e9a14SMatthew G. Knepley } else {
931412e9a14SMatthew G. Knepley ++ctRecv[remoteDepths[p].rank];
932412e9a14SMatthew G. Knepley }
933412e9a14SMatthew G. Knepley }
934412e9a14SMatthew G. Knepley {
935412e9a14SMatthew G. Knepley PetscInt depths[4], dims[4], shift = 0, i, c;
936412e9a14SMatthew G. Knepley
9378238f61eSMatthew G. Knepley /* Cells (depth), Vertices (0), Faces (depth-1), Edges (1)
938476787b7SMatthew G. Knepley Consider DM_POLYTOPE_FV_GHOST, DM_POLYTOPE_INTERIOR_GHOST and DM_POLYTOPE_UNKNOWN_CELL as cells
9398238f61eSMatthew G. Knepley */
9409371c9d4SSatish Balay depths[0] = depth;
9419371c9d4SSatish Balay depths[1] = 0;
9429371c9d4SSatish Balay depths[2] = depth - 1;
9439371c9d4SSatish Balay depths[3] = 1;
9449371c9d4SSatish Balay dims[0] = dim;
9459371c9d4SSatish Balay dims[1] = 0;
9469371c9d4SSatish Balay dims[2] = dim - 1;
9479371c9d4SSatish Balay dims[3] = 1;
948412e9a14SMatthew G. Knepley for (i = 0; i <= depth; ++i) {
949412e9a14SMatthew G. Knepley const PetscInt dep = depths[i];
950412e9a14SMatthew G. Knepley const PetscInt dim = dims[i];
951412e9a14SMatthew G. Knepley
952412e9a14SMatthew G. Knepley for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
953476787b7SMatthew G. Knepley if (DMPolytopeTypeGetDim((DMPolytopeType)c) != dim && !(i == 0 && (c == DM_POLYTOPE_FV_GHOST || c == DM_POLYTOPE_INTERIOR_GHOST || c == DM_POLYTOPE_UNKNOWN_CELL))) continue;
954412e9a14SMatthew G. Knepley ctShift[c] = shift;
955412e9a14SMatthew G. Knepley shift += ctRecv[c];
956412e9a14SMatthew G. Knepley }
957412e9a14SMatthew G. Knepley depthShift[dep] = shift;
958412e9a14SMatthew G. Knepley shift += depthRecv[dep];
959412e9a14SMatthew G. Knepley }
960412e9a14SMatthew G. Knepley for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
961412e9a14SMatthew G. Knepley const PetscInt ctDim = DMPolytopeTypeGetDim((DMPolytopeType)c);
962412e9a14SMatthew G. Knepley
963b6555650SPierre Jolivet if ((ctDim < 0 || ctDim > dim) && c != DM_POLYTOPE_FV_GHOST && c != DM_POLYTOPE_INTERIOR_GHOST && c != DM_POLYTOPE_UNKNOWN_CELL) {
964412e9a14SMatthew G. Knepley ctShift[c] = shift;
965412e9a14SMatthew G. Knepley shift += ctRecv[c];
966412e9a14SMatthew G. Knepley }
967412e9a14SMatthew G. Knepley }
968412e9a14SMatthew G. Knepley }
969a9f1d5b2SMichael Lange /* Derive a new local permutation based on stratified indices */
9709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &ilocal));
9717fab53ddSMatthew G. Knepley for (p = 0; p < nleaves; ++p) {
972412e9a14SMatthew G. Knepley const DMPolytopeType ct = (DMPolytopeType)remoteDepths[p].rank;
9737fab53ddSMatthew G. Knepley
974412e9a14SMatthew G. Knepley ilocal[p] = ctShift[ct] + ctIdx[ct];
975412e9a14SMatthew G. Knepley ++ctIdx[ct];
976412e9a14SMatthew G. Knepley }
9779566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, migrationSF));
9789566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*migrationSF, "Migration SF"));
9799566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*migrationSF, nroots, nleaves, ilocal, PETSC_OWN_POINTER, (PetscSFNode *)iremote, PETSC_COPY_VALUES));
9809566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointDepths, remoteDepths));
9819566063dSJacob Faibussowitsch PetscCall(PetscFree6(depthRecv, depthShift, depthIdx, ctRecv, ctShift, ctIdx));
9829566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartStratSF, dm, 0, 0, 0));
9833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
984a9f1d5b2SMichael Lange }
985a9f1d5b2SMichael Lange
98670034214SMatthew G. Knepley /*@
98720f4b53cSBarry Smith DMPlexDistributeField - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution
98870034214SMatthew G. Knepley
98920f4b53cSBarry Smith Collective
99070034214SMatthew G. Knepley
99170034214SMatthew G. Knepley Input Parameters:
99220f4b53cSBarry Smith + dm - The `DMPLEX` object
99320f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern
99420f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout
995cb15cd0eSMatthew G. Knepley - originalVec - The existing data in a local vector
99670034214SMatthew G. Knepley
99770034214SMatthew G. Knepley Output Parameters:
99820f4b53cSBarry Smith + newSection - The `PetscSF` describing the new data layout
999cb15cd0eSMatthew G. Knepley - newVec - The new data in a local vector
100070034214SMatthew G. Knepley
100170034214SMatthew G. Knepley Level: developer
100270034214SMatthew G. Knepley
1003*6964b6c7SJames Wright .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeFieldIS()`, `DMPlexDistributeData()`, `PetscSectionMigrateData()`
100470034214SMatthew G. Knepley @*/
DMPlexDistributeField(DM dm,PetscSF pointSF,PetscSection originalSection,Vec originalVec,PetscSection newSection,Vec newVec)1005d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec)
1006d71ae5a4SJacob Faibussowitsch {
100770034214SMatthew G. Knepley PetscSF fieldSF;
100870034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize;
100970034214SMatthew G. Knepley PetscScalar *originalValues, *newValues;
101070034214SMatthew G. Knepley
101170034214SMatthew G. Knepley PetscFunctionBegin;
10129566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeField, dm, 0, 0, 0));
10139566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection));
101470034214SMatthew G. Knepley
10159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize));
10169566063dSJacob Faibussowitsch PetscCall(VecSetSizes(newVec, fieldSize, PETSC_DETERMINE));
10179566063dSJacob Faibussowitsch PetscCall(VecSetType(newVec, dm->vectype));
101870034214SMatthew G. Knepley
10199566063dSJacob Faibussowitsch PetscCall(VecGetArray(originalVec, &originalValues));
10209566063dSJacob Faibussowitsch PetscCall(VecGetArray(newVec, &newValues));
10219566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF));
10229566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets));
10239566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues, MPI_REPLACE));
10249566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues, MPI_REPLACE));
10259566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF));
10269566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(newVec, &newValues));
10279566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(originalVec, &originalValues));
10289566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeField, dm, 0, 0, 0));
10293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
103070034214SMatthew G. Knepley }
103170034214SMatthew G. Knepley
103270034214SMatthew G. Knepley /*@
103320f4b53cSBarry Smith DMPlexDistributeFieldIS - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution
103470034214SMatthew G. Knepley
103520f4b53cSBarry Smith Collective
103670034214SMatthew G. Knepley
103770034214SMatthew G. Knepley Input Parameters:
103820f4b53cSBarry Smith + dm - The `DMPLEX` object
103920f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern
104020f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout
104170034214SMatthew G. Knepley - originalIS - The existing data
104270034214SMatthew G. Knepley
104370034214SMatthew G. Knepley Output Parameters:
104420f4b53cSBarry Smith + newSection - The `PetscSF` describing the new data layout
104570034214SMatthew G. Knepley - newIS - The new data
104670034214SMatthew G. Knepley
104770034214SMatthew G. Knepley Level: developer
104870034214SMatthew G. Knepley
1049*6964b6c7SJames Wright .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexDistributeData()`, `PetscSectionMigrateData()`
105070034214SMatthew G. Knepley @*/
DMPlexDistributeFieldIS(DM dm,PetscSF pointSF,PetscSection originalSection,IS originalIS,PetscSection newSection,IS * newIS)1051d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeFieldIS(DM dm, PetscSF pointSF, PetscSection originalSection, IS originalIS, PetscSection newSection, IS *newIS)
1052d71ae5a4SJacob Faibussowitsch {
1053*6964b6c7SJames Wright PetscInt *newValues, fieldSize;
105470034214SMatthew G. Knepley const PetscInt *originalValues;
105570034214SMatthew G. Knepley
105670034214SMatthew G. Knepley PetscFunctionBegin;
10579566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeField, dm, 0, 0, 0));
1058*6964b6c7SJames Wright PetscCall(ISGetIndices(originalIS, &originalValues));
1059*6964b6c7SJames Wright PetscCall(PetscSectionMigrateData(pointSF, MPIU_INT, originalSection, originalValues, newSection, (void **)&newValues, NULL));
1060*6964b6c7SJames Wright PetscCall(ISRestoreIndices(originalIS, &originalValues));
106170034214SMatthew G. Knepley
10629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize));
10639566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pointSF), fieldSize, newValues, PETSC_OWN_POINTER, newIS));
10649566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeField, dm, 0, 0, 0));
10653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
106670034214SMatthew G. Knepley }
106770034214SMatthew G. Knepley
106870034214SMatthew G. Knepley /*@
106920f4b53cSBarry Smith DMPlexDistributeData - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution
107070034214SMatthew G. Knepley
107120f4b53cSBarry Smith Collective
107270034214SMatthew G. Knepley
107370034214SMatthew G. Knepley Input Parameters:
107420f4b53cSBarry Smith + dm - The `DMPLEX` object
107520f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern
107620f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout
107770034214SMatthew G. Knepley . datatype - The type of data
107870034214SMatthew G. Knepley - originalData - The existing data
107970034214SMatthew G. Knepley
108070034214SMatthew G. Knepley Output Parameters:
108120f4b53cSBarry Smith + newSection - The `PetscSection` describing the new data layout
108270034214SMatthew G. Knepley - newData - The new data
108370034214SMatthew G. Knepley
108470034214SMatthew G. Knepley Level: developer
108570034214SMatthew G. Knepley
1086*6964b6c7SJames Wright Note:
1087*6964b6c7SJames Wright This is simply a wrapper around `PetscSectionMigrateData()`, but includes DM-specific logging.
1088*6964b6c7SJames Wright
1089*6964b6c7SJames Wright .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `PetscSectionMigrateData()`
109070034214SMatthew G. Knepley @*/
DMPlexDistributeData(DM dm,PetscSF pointSF,PetscSection originalSection,MPI_Datatype datatype,void * originalData,PetscSection newSection,void ** newData)1091d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeData(DM dm, PetscSF pointSF, PetscSection originalSection, MPI_Datatype datatype, void *originalData, PetscSection newSection, void **newData)
1092d71ae5a4SJacob Faibussowitsch {
109370034214SMatthew G. Knepley PetscFunctionBegin;
10949566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeData, dm, 0, 0, 0));
1095*6964b6c7SJames Wright PetscCall(PetscSectionMigrateData(pointSF, datatype, originalSection, originalData, newSection, newData, NULL));
10969566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeData, dm, 0, 0, 0));
10973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
109870034214SMatthew G. Knepley }
109970034214SMatthew G. Knepley
DMPlexDistributeCones(DM dm,PetscSF migrationSF,ISLocalToGlobalMapping original,ISLocalToGlobalMapping renumbering,DM dmParallel)1100d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeCones(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel)
1101d71ae5a4SJacob Faibussowitsch {
110257508eceSPierre Jolivet DM_Plex *pmesh = (DM_Plex *)dmParallel->data;
1103cc71bff1SMichael Lange MPI_Comm comm;
1104cc71bff1SMichael Lange PetscSF coneSF;
1105cc71bff1SMichael Lange PetscSection originalConeSection, newConeSection;
1106ac04eaf7SToby Isaac PetscInt *remoteOffsets, *cones, *globCones, *newCones, newConesSize;
1107cc71bff1SMichael Lange PetscBool flg;
1108cc71bff1SMichael Lange
1109cc71bff1SMichael Lange PetscFunctionBegin;
1110cc71bff1SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11110c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5);
11129566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeCones, dm, 0, 0, 0));
1113cc71bff1SMichael Lange /* Distribute cone section */
11149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
11159566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &originalConeSection));
11169566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dmParallel, &newConeSection));
11179566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(migrationSF, originalConeSection, &remoteOffsets, newConeSection));
11189566063dSJacob Faibussowitsch PetscCall(DMSetUp(dmParallel));
1119cc71bff1SMichael Lange /* Communicate and renumber cones */
11209566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(migrationSF, originalConeSection, remoteOffsets, newConeSection, &coneSF));
11219566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets));
11229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones));
1123ac04eaf7SToby Isaac if (original) {
1124ac04eaf7SToby Isaac PetscInt numCones;
1125ac04eaf7SToby Isaac
11269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(originalConeSection, &numCones));
11279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCones, &globCones));
11289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(original, numCones, cones, globCones));
1129367003a6SStefano Zampini } else {
1130ac04eaf7SToby Isaac globCones = cones;
1131ac04eaf7SToby Isaac }
11329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dmParallel, &newCones));
11339566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coneSF, MPIU_INT, globCones, newCones, MPI_REPLACE));
11349566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coneSF, MPIU_INT, globCones, newCones, MPI_REPLACE));
11351baa6e33SBarry Smith if (original) PetscCall(PetscFree(globCones));
11369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newConeSection, &newConesSize));
11379566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones));
113876bd3646SJed Brown if (PetscDefined(USE_DEBUG)) {
11393533c52bSMatthew G. Knepley PetscInt p;
11403533c52bSMatthew G. Knepley PetscBool valid = PETSC_TRUE;
11413533c52bSMatthew G. Knepley for (p = 0; p < newConesSize; ++p) {
11429371c9d4SSatish Balay if (newCones[p] < 0) {
11439371c9d4SSatish Balay valid = PETSC_FALSE;
11449371c9d4SSatish Balay PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Point %" PetscInt_FMT " not in overlap SF\n", PetscGlobalRank, p));
11459371c9d4SSatish Balay }
11463533c52bSMatthew G. Knepley }
114728b400f6SJacob Faibussowitsch PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map");
11483533c52bSMatthew G. Knepley }
11499566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-cones_view", &flg));
1150cc71bff1SMichael Lange if (flg) {
11519566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Serial Cone Section:\n"));
11529566063dSJacob Faibussowitsch PetscCall(PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_(comm)));
11539566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Parallel Cone Section:\n"));
11549566063dSJacob Faibussowitsch PetscCall(PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_(comm)));
11559566063dSJacob Faibussowitsch PetscCall(PetscSFView(coneSF, NULL));
1156cc71bff1SMichael Lange }
11579566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dm, &cones));
11589566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dmParallel, &newCones));
11599566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones, MPI_REPLACE));
11609566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones, MPI_REPLACE));
11619566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coneSF));
11629566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeCones, dm, 0, 0, 0));
1163eaf898f9SPatrick Sanan /* Create supports and stratify DMPlex */
1164cc71bff1SMichael Lange {
1165cc71bff1SMichael Lange PetscInt pStart, pEnd;
1166cc71bff1SMichael Lange
11679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd));
11689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(pmesh->supportSection, pStart, pEnd));
1169cc71bff1SMichael Lange }
11709566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dmParallel));
11719566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dmParallel));
11721cf84007SMatthew G. Knepley {
11731cf84007SMatthew G. Knepley PetscBool useCone, useClosure, useAnchors;
11741cf84007SMatthew G. Knepley
11759566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure));
11769566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dmParallel, useCone, useClosure));
11779566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors));
11789566063dSJacob Faibussowitsch PetscCall(DMPlexSetAdjacencyUseAnchors(dmParallel, useAnchors));
11791cf84007SMatthew G. Knepley }
11803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1181cc71bff1SMichael Lange }
1182cc71bff1SMichael Lange
DMPlexDistributeCoordinates(DM dm,PetscSF migrationSF,DM dmParallel)1183d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeCoordinates(DM dm, PetscSF migrationSF, DM dmParallel)
1184d71ae5a4SJacob Faibussowitsch {
11850df0e737SMichael Lange MPI_Comm comm;
11869318fe57SMatthew G. Knepley DM cdm, cdmParallel;
11870df0e737SMichael Lange PetscSection originalCoordSection, newCoordSection;
11880df0e737SMichael Lange Vec originalCoordinates, newCoordinates;
11890df0e737SMichael Lange PetscInt bs;
11900df0e737SMichael Lange const char *name;
11914fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L;
11920df0e737SMichael Lange
11930df0e737SMichael Lange PetscFunctionBegin;
11940df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11950c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3);
11960df0e737SMichael Lange
11979566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
11986858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm));
11996858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dmParallel, &cdmParallel));
12006858538eSMatthew G. Knepley PetscCall(DMCopyDisc(cdm, cdmParallel));
12019566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &originalCoordSection));
12029566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmParallel, &newCoordSection));
12039566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &originalCoordinates));
12040df0e737SMichael Lange if (originalCoordinates) {
12059566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates));
12069566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalCoordinates, &name));
12079566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)newCoordinates, name));
12080df0e737SMichael Lange
12099566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates));
12109566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmParallel, newCoordinates));
12119566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(originalCoordinates, &bs));
12129566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(newCoordinates, bs));
12139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&newCoordinates));
12140df0e737SMichael Lange }
12156858538eSMatthew G. Knepley
12166858538eSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
12174fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L));
12184fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmParallel, maxCell, Lstart, L));
12196858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdm));
12206858538eSMatthew G. Knepley if (cdm) {
12216858538eSMatthew G. Knepley PetscCall(DMClone(dmParallel, &cdmParallel));
12226858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmParallel, cdmParallel));
12239566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(cdm, cdmParallel));
12246858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmParallel));
12256858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &originalCoordSection));
12266858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &originalCoordinates));
12276858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(comm, &newCoordSection));
12286858538eSMatthew G. Knepley if (originalCoordinates) {
12296858538eSMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates));
12306858538eSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)originalCoordinates, &name));
12316858538eSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)newCoordinates, name));
12326858538eSMatthew G. Knepley
12336858538eSMatthew G. Knepley PetscCall(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates));
12346858538eSMatthew G. Knepley PetscCall(VecGetBlockSize(originalCoordinates, &bs));
12356858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(newCoordinates, bs));
12366858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(dmParallel, bs, newCoordSection));
12376858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmParallel, newCoordinates));
12386858538eSMatthew G. Knepley PetscCall(VecDestroy(&newCoordinates));
12396858538eSMatthew G. Knepley }
12406858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&newCoordSection));
12416858538eSMatthew G. Knepley }
12423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
12430df0e737SMichael Lange }
12440df0e737SMichael Lange
DMPlexDistributeLabels(DM dm,PetscSF migrationSF,DM dmParallel)1245d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeLabels(DM dm, PetscSF migrationSF, DM dmParallel)
1246d71ae5a4SJacob Faibussowitsch {
1247df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
12480df0e737SMichael Lange MPI_Comm comm;
12497980c9d4SMatthew G. Knepley DMLabel depthLabel;
12500df0e737SMichael Lange PetscMPIInt rank;
12517980c9d4SMatthew G. Knepley PetscInt depth, d, numLabels, numLocalLabels, l;
1252df0420ecSMatthew G. Knepley PetscBool hasLabels = PETSC_FALSE, lsendDepth, sendDepth;
1253df0420ecSMatthew G. Knepley PetscObjectState depthState = -1;
12540df0e737SMichael Lange
12550df0e737SMichael Lange PetscFunctionBegin;
12560df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
12570c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3);
12580c86c063SLisandro Dalcin
12599566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeLabels, dm, 0, 0, 0));
12609566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
12619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
12620df0e737SMichael Lange
1263df0420ecSMatthew G. Knepley /* If the user has changed the depth label, communicate it instead */
12649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
12659566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
12669566063dSJacob Faibussowitsch if (depthLabel) PetscCall(PetscObjectStateGet((PetscObject)depthLabel, &depthState));
1267df0420ecSMatthew G. Knepley lsendDepth = mesh->depthState != depthState ? PETSC_TRUE : PETSC_FALSE;
12685440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lsendDepth, &sendDepth, 1, MPI_C_BOOL, MPI_LOR, comm));
1269df0420ecSMatthew G. Knepley if (sendDepth) {
12709566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dmParallel, &dmParallel->depthLabel));
12719566063dSJacob Faibussowitsch PetscCall(DMRemoveLabelBySelf(dmParallel, &dmParallel->depthLabel, PETSC_FALSE));
1272df0420ecSMatthew G. Knepley }
1273d995df53SMatthew G. Knepley /* Everyone must have either the same number of labels, or none */
12749566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLocalLabels));
1275d995df53SMatthew G. Knepley numLabels = numLocalLabels;
12769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm));
1277627847f0SMatthew G. Knepley if (numLabels == numLocalLabels) hasLabels = PETSC_TRUE;
12785d80c0bfSVaclav Hapla for (l = 0; l < numLabels; ++l) {
1279bdd2d751SMichael Lange DMLabel label = NULL, labelNew = NULL;
128083e10cb3SLisandro Dalcin PetscBool isDepth, lisOutput = PETSC_TRUE, isOutput;
1281d67d17b1SMatthew G. Knepley const char *name = NULL;
12820df0e737SMichael Lange
1283d67d17b1SMatthew G. Knepley if (hasLabels) {
12849566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(dm, l, &label));
12850df0e737SMichael Lange /* Skip "depth" because it is recreated */
12869566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)label, &name));
12879566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth));
1288bbcf679cSJacob Faibussowitsch } else {
1289bbcf679cSJacob Faibussowitsch isDepth = PETSC_FALSE;
1290d67d17b1SMatthew G. Knepley }
12915440e5dcSBarry Smith PetscCallMPI(MPI_Bcast(&isDepth, 1, MPI_C_BOOL, 0, comm));
129283e10cb3SLisandro Dalcin if (isDepth && !sendDepth) continue;
12939566063dSJacob Faibussowitsch PetscCall(DMLabelDistribute(label, migrationSF, &labelNew));
129483e10cb3SLisandro Dalcin if (isDepth) {
12957980c9d4SMatthew G. Knepley /* Put in any missing strata which can occur if users are managing the depth label themselves */
12967980c9d4SMatthew G. Knepley PetscInt gdepth;
12977980c9d4SMatthew G. Knepley
1298462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&depth, &gdepth, 1, MPIU_INT, MPI_MAX, comm));
129963a3b9bcSJacob Faibussowitsch PetscCheck(!(depth >= 0) || !(gdepth != depth), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %" PetscInt_FMT " != %" PetscInt_FMT, depth, gdepth);
13007980c9d4SMatthew G. Knepley for (d = 0; d <= gdepth; ++d) {
13017980c9d4SMatthew G. Knepley PetscBool has;
13027980c9d4SMatthew G. Knepley
13039566063dSJacob Faibussowitsch PetscCall(DMLabelHasStratum(labelNew, d, &has));
13049566063dSJacob Faibussowitsch if (!has) PetscCall(DMLabelAddStratum(labelNew, d));
13057980c9d4SMatthew G. Knepley }
13067980c9d4SMatthew G. Knepley }
13079566063dSJacob Faibussowitsch PetscCall(DMAddLabel(dmParallel, labelNew));
130883e10cb3SLisandro Dalcin /* Put the output flag in the new label */
13099566063dSJacob Faibussowitsch if (hasLabels) PetscCall(DMGetLabelOutput(dm, name, &lisOutput));
13105440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lisOutput, &isOutput, 1, MPI_C_BOOL, MPI_LAND, comm));
13119566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)labelNew, &name));
13129566063dSJacob Faibussowitsch PetscCall(DMSetLabelOutput(dmParallel, name, isOutput));
13139566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&labelNew));
13140df0e737SMichael Lange }
1315695799ffSMatthew G. Knepley {
1316695799ffSMatthew G. Knepley DMLabel ctLabel;
1317695799ffSMatthew G. Knepley
1318695799ffSMatthew G. Knepley // Reset label for fast lookup
1319695799ffSMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dmParallel, &ctLabel));
1320695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
1321695799ffSMatthew G. Knepley }
13229566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeLabels, dm, 0, 0, 0));
13233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13240df0e737SMichael Lange }
13250df0e737SMichael Lange
DMPlexDistributeSetupTree(DM dm,PetscSF migrationSF,ISLocalToGlobalMapping original,ISLocalToGlobalMapping renumbering,DM dmParallel)1326d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeSetupTree(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel)
1327d71ae5a4SJacob Faibussowitsch {
132815078cd4SMichael Lange DM_Plex *mesh = (DM_Plex *)dm->data;
132957508eceSPierre Jolivet DM_Plex *pmesh = (DM_Plex *)dmParallel->data;
1330a6f36705SMichael Lange MPI_Comm comm;
1331a6f36705SMichael Lange DM refTree;
1332a6f36705SMichael Lange PetscSection origParentSection, newParentSection;
1333a6f36705SMichael Lange PetscInt *origParents, *origChildIDs;
1334a6f36705SMichael Lange PetscBool flg;
1335a6f36705SMichael Lange
1336a6f36705SMichael Lange PetscFunctionBegin;
1337a6f36705SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
13380c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5);
13399566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
1340a6f36705SMichael Lange
1341a6f36705SMichael Lange /* Set up tree */
13429566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree));
13439566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(dmParallel, refTree));
13449566063dSJacob Faibussowitsch PetscCall(DMPlexGetTree(dm, &origParentSection, &origParents, &origChildIDs, NULL, NULL));
1345a6f36705SMichael Lange if (origParentSection) {
1346a6f36705SMichael Lange PetscInt pStart, pEnd;
134708633170SToby Isaac PetscInt *newParents, *newChildIDs, *globParents;
1348a6f36705SMichael Lange PetscInt *remoteOffsetsParents, newParentSize;
1349a6f36705SMichael Lange PetscSF parentSF;
1350a6f36705SMichael Lange
13519566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmParallel, &pStart, &pEnd));
13529566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmParallel), &newParentSection));
13539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newParentSection, pStart, pEnd));
13549566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(migrationSF, origParentSection, &remoteOffsetsParents, newParentSection));
13559566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(migrationSF, origParentSection, remoteOffsetsParents, newParentSection, &parentSF));
13569566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsParents));
13579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newParentSection, &newParentSize));
13589566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(newParentSize, &newParents, newParentSize, &newChildIDs));
135908633170SToby Isaac if (original) {
136008633170SToby Isaac PetscInt numParents;
136108633170SToby Isaac
13629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(origParentSection, &numParents));
13639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numParents, &globParents));
13649566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(original, numParents, origParents, globParents));
13659371c9d4SSatish Balay } else {
136608633170SToby Isaac globParents = origParents;
136708633170SToby Isaac }
13689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(parentSF, MPIU_INT, globParents, newParents, MPI_REPLACE));
13699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(parentSF, MPIU_INT, globParents, newParents, MPI_REPLACE));
13701baa6e33SBarry Smith if (original) PetscCall(PetscFree(globParents));
13719566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(parentSF, MPIU_INT, origChildIDs, newChildIDs, MPI_REPLACE));
13729566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(parentSF, MPIU_INT, origChildIDs, newChildIDs, MPI_REPLACE));
13739566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newParentSize, newParents, NULL, newParents));
137476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) {
13754a54e071SToby Isaac PetscInt p;
13764a54e071SToby Isaac PetscBool valid = PETSC_TRUE;
13774a54e071SToby Isaac for (p = 0; p < newParentSize; ++p) {
13789371c9d4SSatish Balay if (newParents[p] < 0) {
13799371c9d4SSatish Balay valid = PETSC_FALSE;
13809371c9d4SSatish Balay PetscCall(PetscPrintf(PETSC_COMM_SELF, "Point %" PetscInt_FMT " not in overlap SF\n", p));
13819371c9d4SSatish Balay }
13824a54e071SToby Isaac }
138328b400f6SJacob Faibussowitsch PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map");
13844a54e071SToby Isaac }
13859566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-parents_view", &flg));
1386a6f36705SMichael Lange if (flg) {
13879566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Serial Parent Section: \n"));
13889566063dSJacob Faibussowitsch PetscCall(PetscSectionView(origParentSection, PETSC_VIEWER_STDOUT_(comm)));
13899566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Parallel Parent Section: \n"));
13909566063dSJacob Faibussowitsch PetscCall(PetscSectionView(newParentSection, PETSC_VIEWER_STDOUT_(comm)));
13919566063dSJacob Faibussowitsch PetscCall(PetscSFView(parentSF, NULL));
1392a6f36705SMichael Lange }
13939566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(dmParallel, newParentSection, newParents, newChildIDs));
13949566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newParentSection));
13959566063dSJacob Faibussowitsch PetscCall(PetscFree2(newParents, newChildIDs));
13969566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&parentSF));
1397a6f36705SMichael Lange }
139815078cd4SMichael Lange pmesh->useAnchors = mesh->useAnchors;
13993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1400a6f36705SMichael Lange }
14010df0e737SMichael Lange
140298ba2d7fSLawrence Mitchell /*@
140320f4b53cSBarry Smith DMPlexSetPartitionBalance - Should distribution of the `DM` attempt to balance the shared point partition?
140498ba2d7fSLawrence Mitchell
140598ba2d7fSLawrence Mitchell Input Parameters:
140620f4b53cSBarry Smith + dm - The `DMPLEX` object
140798ba2d7fSLawrence Mitchell - flg - Balance the partition?
140898ba2d7fSLawrence Mitchell
140998ba2d7fSLawrence Mitchell Level: intermediate
141098ba2d7fSLawrence Mitchell
141120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetPartitionBalance()`
141298ba2d7fSLawrence Mitchell @*/
DMPlexSetPartitionBalance(DM dm,PetscBool flg)1413d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetPartitionBalance(DM dm, PetscBool flg)
1414d71ae5a4SJacob Faibussowitsch {
141598ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data;
141698ba2d7fSLawrence Mitchell
141798ba2d7fSLawrence Mitchell PetscFunctionBegin;
141898ba2d7fSLawrence Mitchell mesh->partitionBalance = flg;
14193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
142098ba2d7fSLawrence Mitchell }
142198ba2d7fSLawrence Mitchell
142298ba2d7fSLawrence Mitchell /*@
142320f4b53cSBarry Smith DMPlexGetPartitionBalance - Does distribution of the `DM` attempt to balance the shared point partition?
142498ba2d7fSLawrence Mitchell
142598ba2d7fSLawrence Mitchell Input Parameter:
142620f4b53cSBarry Smith . dm - The `DMPLEX` object
142798ba2d7fSLawrence Mitchell
142898ba2d7fSLawrence Mitchell Output Parameter:
1429a2b725a8SWilliam Gropp . flg - Balance the partition?
143098ba2d7fSLawrence Mitchell
143198ba2d7fSLawrence Mitchell Level: intermediate
143298ba2d7fSLawrence Mitchell
143320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexSetPartitionBalance()`
143498ba2d7fSLawrence Mitchell @*/
DMPlexGetPartitionBalance(DM dm,PetscBool * flg)1435d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPartitionBalance(DM dm, PetscBool *flg)
1436d71ae5a4SJacob Faibussowitsch {
143798ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data;
143898ba2d7fSLawrence Mitchell
143998ba2d7fSLawrence Mitchell PetscFunctionBegin;
144098ba2d7fSLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14414f572ea9SToby Isaac PetscAssertPointer(flg, 2);
144298ba2d7fSLawrence Mitchell *flg = mesh->partitionBalance;
14433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
144498ba2d7fSLawrence Mitchell }
144598ba2d7fSLawrence Mitchell
1446fc02256fSLawrence Mitchell typedef struct {
1447fc02256fSLawrence Mitchell PetscInt vote, rank, index;
1448fc02256fSLawrence Mitchell } Petsc3Int;
1449fc02256fSLawrence Mitchell
1450fc02256fSLawrence Mitchell /* MaxLoc, but carry a third piece of information around */
MaxLocCarry(void * in_,void * inout_,PetscMPIInt * len_,MPI_Datatype * dtype)1451d71ae5a4SJacob Faibussowitsch static void MPIAPI MaxLocCarry(void *in_, void *inout_, PetscMPIInt *len_, MPI_Datatype *dtype)
1452d71ae5a4SJacob Faibussowitsch {
1453fc02256fSLawrence Mitchell Petsc3Int *a = (Petsc3Int *)inout_;
1454fc02256fSLawrence Mitchell Petsc3Int *b = (Petsc3Int *)in_;
1455fc02256fSLawrence Mitchell PetscInt i, len = *len_;
1456fc02256fSLawrence Mitchell for (i = 0; i < len; i++) {
1457fc02256fSLawrence Mitchell if (a[i].vote < b[i].vote) {
1458fc02256fSLawrence Mitchell a[i].vote = b[i].vote;
1459fc02256fSLawrence Mitchell a[i].rank = b[i].rank;
1460fc02256fSLawrence Mitchell a[i].index = b[i].index;
1461fc02256fSLawrence Mitchell } else if (a[i].vote <= b[i].vote) {
1462fc02256fSLawrence Mitchell if (a[i].rank >= b[i].rank) {
1463fc02256fSLawrence Mitchell a[i].rank = b[i].rank;
1464fc02256fSLawrence Mitchell a[i].index = b[i].index;
1465fc02256fSLawrence Mitchell }
1466fc02256fSLawrence Mitchell }
1467fc02256fSLawrence Mitchell }
1468fc02256fSLawrence Mitchell }
1469fc02256fSLawrence Mitchell
1470cc4c1da9SBarry Smith /*@
147120f4b53cSBarry Smith DMPlexCreatePointSF - Build a point `PetscSF` from an `PetscSF` describing a point migration
1472f5bf2dbfSMichael Lange
1473064ec1f3Sprj- Input Parameters:
147420f4b53cSBarry Smith + dm - The source `DMPLEX` object
1475f5bf2dbfSMichael Lange . migrationSF - The star forest that describes the parallel point remapping
1476d8d19677SJose E. Roman - ownership - Flag causing a vote to determine point ownership
1477f5bf2dbfSMichael Lange
1478f5bf2dbfSMichael Lange Output Parameter:
147920f4b53cSBarry Smith . pointSF - The star forest describing the point overlap in the remapped `DM`
14803618482eSVaclav Hapla
1481f5bf2dbfSMichael Lange Level: developer
1482f5bf2dbfSMichael Lange
148320f4b53cSBarry Smith Note:
148420f4b53cSBarry Smith Output `pointSF` is guaranteed to have the array of local indices (leaves) sorted.
148520f4b53cSBarry Smith
148620f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()`
1487f5bf2dbfSMichael Lange @*/
DMPlexCreatePointSF(DM dm,PetscSF migrationSF,PetscBool ownership,PetscSF * pointSF)1488d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointSF(DM dm, PetscSF migrationSF, PetscBool ownership, PetscSF *pointSF)
1489d71ae5a4SJacob Faibussowitsch {
149023193802SMatthew G. Knepley PetscMPIInt rank, size;
14911627f6ccSMichael Lange PetscInt p, nroots, nleaves, idx, npointLeaves;
1492f5bf2dbfSMichael Lange PetscInt *pointLocal;
1493f5bf2dbfSMichael Lange const PetscInt *leaves;
1494f5bf2dbfSMichael Lange const PetscSFNode *roots;
1495f5bf2dbfSMichael Lange PetscSFNode *rootNodes, *leafNodes, *pointRemote;
149623193802SMatthew G. Knepley Vec shifts;
1497cae3e4f3SLawrence Mitchell const PetscInt numShifts = 13759;
149823193802SMatthew G. Knepley const PetscScalar *shift = NULL;
149923193802SMatthew G. Knepley const PetscBool shiftDebug = PETSC_FALSE;
150098ba2d7fSLawrence Mitchell PetscBool balance;
1501f5bf2dbfSMichael Lange
1502f5bf2dbfSMichael Lange PetscFunctionBegin;
1503f5bf2dbfSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
15049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
15059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
15069566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreatePointSF, dm, 0, 0, 0));
1507907a3e9cSStefano Zampini PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), pointSF));
1508907a3e9cSStefano Zampini PetscCall(PetscSFSetFromOptions(*pointSF));
1509907a3e9cSStefano Zampini if (size == 1) PetscFunctionReturn(PETSC_SUCCESS);
1510f5bf2dbfSMichael Lange
15119566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitionBalance(dm, &balance));
15129566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(migrationSF, &nroots, &nleaves, &leaves, &roots));
15139566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &rootNodes, nleaves, &leafNodes));
1514f5bf2dbfSMichael Lange if (ownership) {
1515fc02256fSLawrence Mitchell MPI_Op op;
1516fc02256fSLawrence Mitchell MPI_Datatype datatype;
1517fc02256fSLawrence Mitchell Petsc3Int *rootVote = NULL, *leafVote = NULL;
15186497c311SBarry Smith
151923193802SMatthew 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. */
152098ba2d7fSLawrence Mitchell if (balance) {
152123193802SMatthew G. Knepley PetscRandom r;
152223193802SMatthew G. Knepley
15239566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_SELF, &r));
15249566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(r, 0, 2467 * size));
15259566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &shifts));
15269566063dSJacob Faibussowitsch PetscCall(VecSetSizes(shifts, numShifts, numShifts));
15279566063dSJacob Faibussowitsch PetscCall(VecSetType(shifts, VECSTANDARD));
15289566063dSJacob Faibussowitsch PetscCall(VecSetRandom(shifts, r));
15299566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&r));
15309566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(shifts, &shift));
153123193802SMatthew G. Knepley }
153223193802SMatthew G. Knepley
15339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nroots, &rootVote));
15349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &leafVote));
153523193802SMatthew G. Knepley /* Point ownership vote: Process with highest rank owns shared points */
1536f5bf2dbfSMichael Lange for (p = 0; p < nleaves; ++p) {
153723193802SMatthew G. Knepley if (shiftDebug) {
15389371c9d4SSatish Balay PetscCall(PetscSynchronizedPrintf(PetscObjectComm((PetscObject)dm), "[%d] Point %" PetscInt_FMT " RemotePoint %" PetscInt_FMT " Shift %" PetscInt_FMT " MyRank %" PetscInt_FMT "\n", rank, leaves ? leaves[p] : p, roots[p].index,
15399371c9d4SSatish Balay (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]), (rank + (shift ? (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]) : 0)) % size));
154023193802SMatthew G. Knepley }
1541f5bf2dbfSMichael Lange /* Either put in a bid or we know we own it */
1542fc02256fSLawrence Mitchell leafVote[p].vote = (rank + (shift ? (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]) : 0)) % size;
1543fc02256fSLawrence Mitchell leafVote[p].rank = rank;
1544fc02256fSLawrence Mitchell leafVote[p].index = p;
1545f5bf2dbfSMichael Lange }
1546f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) {
15471627f6ccSMichael Lange /* Root must not participate in the reduction, flag so that MAXLOC does not use */
1548fc02256fSLawrence Mitchell rootVote[p].vote = -3;
1549fc02256fSLawrence Mitchell rootVote[p].rank = -3;
1550fc02256fSLawrence Mitchell rootVote[p].index = -3;
1551f5bf2dbfSMichael Lange }
15529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(3, MPIU_INT, &datatype));
15539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&datatype));
15549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(&MaxLocCarry, 1, &op));
15559566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(migrationSF, datatype, leafVote, rootVote, op));
15569566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(migrationSF, datatype, leafVote, rootVote, op));
15579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&op));
15589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&datatype));
1559c091126eSLawrence Mitchell for (p = 0; p < nroots; p++) {
1560835f2295SStefano Zampini rootNodes[p].rank = rootVote[p].rank;
1561fc02256fSLawrence Mitchell rootNodes[p].index = rootVote[p].index;
1562c091126eSLawrence Mitchell }
15639566063dSJacob Faibussowitsch PetscCall(PetscFree(leafVote));
15649566063dSJacob Faibussowitsch PetscCall(PetscFree(rootVote));
1565f5bf2dbfSMichael Lange } else {
1566f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) {
1567f5bf2dbfSMichael Lange rootNodes[p].index = -1;
1568f5bf2dbfSMichael Lange rootNodes[p].rank = rank;
1569fc02256fSLawrence Mitchell }
1570f5bf2dbfSMichael Lange for (p = 0; p < nleaves; p++) {
1571f5bf2dbfSMichael Lange /* Write new local id into old location */
1572ad540459SPierre Jolivet if (roots[p].rank == rank) rootNodes[roots[p].index].index = leaves ? leaves[p] : p;
1573f5bf2dbfSMichael Lange }
1574f5bf2dbfSMichael Lange }
15756497c311SBarry Smith PetscCall(PetscSFBcastBegin(migrationSF, MPIU_SF_NODE, rootNodes, leafNodes, MPI_REPLACE));
15766497c311SBarry Smith PetscCall(PetscSFBcastEnd(migrationSF, MPIU_SF_NODE, rootNodes, leafNodes, MPI_REPLACE));
1577f5bf2dbfSMichael Lange
157823193802SMatthew G. Knepley for (npointLeaves = 0, p = 0; p < nleaves; p++) {
1579b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) npointLeaves++;
158023193802SMatthew G. Knepley }
15819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npointLeaves, &pointLocal));
15829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npointLeaves, &pointRemote));
1583f5bf2dbfSMichael Lange for (idx = 0, p = 0; p < nleaves; p++) {
1584b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) {
15853618482eSVaclav Hapla /* Note that pointLocal is automatically sorted as it is sublist of 0, ..., nleaves-1 */
1586f5bf2dbfSMichael Lange pointLocal[idx] = p;
1587f5bf2dbfSMichael Lange pointRemote[idx] = leafNodes[p];
1588f5bf2dbfSMichael Lange idx++;
1589f5bf2dbfSMichael Lange }
1590f5bf2dbfSMichael Lange }
159123193802SMatthew G. Knepley if (shift) {
15929566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(shifts, &shift));
15939566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shifts));
159423193802SMatthew G. Knepley }
15959566063dSJacob Faibussowitsch if (shiftDebug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), PETSC_STDOUT));
15969566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*pointSF, nleaves, npointLeaves, pointLocal, PETSC_OWN_POINTER, pointRemote, PETSC_OWN_POINTER));
15979566063dSJacob Faibussowitsch PetscCall(PetscFree2(rootNodes, leafNodes));
15989566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreatePointSF, dm, 0, 0, 0));
1599d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, *pointSF, PETSC_FALSE));
16003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1601f5bf2dbfSMichael Lange }
1602f5bf2dbfSMichael Lange
1603cc4c1da9SBarry Smith /*@
160420f4b53cSBarry Smith DMPlexMigrate - Migrates internal `DM` data over the supplied star forest
160515078cd4SMichael Lange
160620f4b53cSBarry Smith Collective
160783655b49SVáclav Hapla
1608064ec1f3Sprj- Input Parameters:
160920f4b53cSBarry Smith + dm - The source `DMPLEX` object
1610d8d19677SJose E. Roman - sf - The star forest communication context describing the migration pattern
161115078cd4SMichael Lange
161215078cd4SMichael Lange Output Parameter:
161320f4b53cSBarry Smith . targetDM - The target `DMPLEX` object
161415078cd4SMichael Lange
1615b9f40539SMichael Lange Level: intermediate
161615078cd4SMichael Lange
161720f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()`
161815078cd4SMichael Lange @*/
DMPlexMigrate(DM dm,PetscSF sf,DM targetDM)1619d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMigrate(DM dm, PetscSF sf, DM targetDM)
1620d71ae5a4SJacob Faibussowitsch {
1621b9f40539SMichael Lange MPI_Comm comm;
1622cc1750acSStefano Zampini PetscInt dim, cdim, nroots;
1623b9f40539SMichael Lange PetscSF sfPoint;
162415078cd4SMichael Lange ISLocalToGlobalMapping ltogMigration;
1625ac04eaf7SToby Isaac ISLocalToGlobalMapping ltogOriginal = NULL;
162615078cd4SMichael Lange
162715078cd4SMichael Lange PetscFunctionBegin;
162815078cd4SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
16299566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Migrate, dm, 0, 0, 0));
16309566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
16319566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
16329566063dSJacob Faibussowitsch PetscCall(DMSetDimension(targetDM, dim));
16339566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim));
16349566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(targetDM, cdim));
163515078cd4SMichael Lange
1636bfb0467fSMichael Lange /* Check for a one-to-all distribution pattern */
16379566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint));
16389566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL));
1639bfb0467fSMichael Lange if (nroots >= 0) {
1640b9f40539SMichael Lange IS isOriginal;
1641ac04eaf7SToby Isaac PetscInt n, size, nleaves;
1642ac04eaf7SToby Isaac PetscInt *numbering_orig, *numbering_new;
1643367003a6SStefano Zampini
1644b9f40539SMichael Lange /* Get the original point numbering */
16459566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &isOriginal));
16469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(isOriginal, <ogOriginal));
16479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(ltogOriginal, &size));
16489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltogOriginal, (const PetscInt **)&numbering_orig));
1649b9f40539SMichael Lange /* Convert to positive global numbers */
16509371c9d4SSatish Balay for (n = 0; n < size; n++) {
16519371c9d4SSatish Balay if (numbering_orig[n] < 0) numbering_orig[n] = -(numbering_orig[n] + 1);
16529371c9d4SSatish Balay }
1653b9f40539SMichael Lange /* Derive the new local-to-global mapping from the old one */
16549566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, NULL, NULL));
16559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &numbering_new));
16569566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, numbering_orig, numbering_new, MPI_REPLACE));
16579566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, numbering_orig, numbering_new, MPI_REPLACE));
16589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, nleaves, numbering_new, PETSC_OWN_POINTER, <ogMigration));
16599566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogOriginal, (const PetscInt **)&numbering_orig));
16609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isOriginal));
166115078cd4SMichael Lange } else {
1662bfb0467fSMichael Lange /* One-to-all distribution pattern: We can derive LToG from SF */
16639566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateSF(sf, 0, <ogMigration));
166415078cd4SMichael Lange }
1665a5a902f7SVaclav Hapla PetscCall(PetscObjectSetName((PetscObject)ltogMigration, "Point renumbering for DM migration"));
1666a5a902f7SVaclav Hapla PetscCall(ISLocalToGlobalMappingViewFromOptions(ltogMigration, (PetscObject)dm, "-partition_view"));
166715078cd4SMichael Lange /* Migrate DM data to target DM */
16689566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeCones(dm, sf, ltogOriginal, ltogMigration, targetDM));
16699566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeLabels(dm, sf, targetDM));
16709566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeCoordinates(dm, sf, targetDM));
16719566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetupTree(dm, sf, ltogOriginal, ltogMigration, targetDM));
16729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<ogOriginal));
16739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<ogMigration));
16749566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Migrate, dm, 0, 0, 0));
16753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
167615078cd4SMichael Lange }
167715078cd4SMichael Lange
167800a1aa47SMatthew G. Knepley /*@
167900a1aa47SMatthew G. Knepley DMPlexRemapMigrationSF - Rewrite the distribution SF to account for overlap
168000a1aa47SMatthew G. Knepley
168100a1aa47SMatthew G. Knepley Collective
168200a1aa47SMatthew G. Knepley
168300a1aa47SMatthew G. Knepley Input Parameters:
168400a1aa47SMatthew G. Knepley + sfOverlap - The `PetscSF` object just for the overlap
168500a1aa47SMatthew G. Knepley - sfMigration - The original distribution `PetscSF` object
168600a1aa47SMatthew G. Knepley
168700a1aa47SMatthew G. Knepley Output Parameters:
168800a1aa47SMatthew G. Knepley . sfMigrationNew - A rewritten `PetscSF` object that incorporates the overlap
168900a1aa47SMatthew G. Knepley
169000a1aa47SMatthew G. Knepley Level: developer
169100a1aa47SMatthew G. Knepley
169200a1aa47SMatthew G. Knepley .seealso: `DMPLEX`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()`, `DMPlexGetOverlap()`
169300a1aa47SMatthew G. Knepley @*/
DMPlexRemapMigrationSF(PetscSF sfOverlap,PetscSF sfMigration,PetscSF * sfMigrationNew)169400a1aa47SMatthew G. Knepley PetscErrorCode DMPlexRemapMigrationSF(PetscSF sfOverlap, PetscSF sfMigration, PetscSF *sfMigrationNew)
169500a1aa47SMatthew G. Knepley {
1696835f2295SStefano Zampini PetscSFNode *newRemote, *permRemote = NULL;
169700a1aa47SMatthew G. Knepley const PetscInt *oldLeaves;
169800a1aa47SMatthew G. Knepley const PetscSFNode *oldRemote;
169900a1aa47SMatthew G. Knepley PetscInt nroots, nleaves, noldleaves;
170000a1aa47SMatthew G. Knepley
170100a1aa47SMatthew G. Knepley PetscFunctionBegin;
170200a1aa47SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfMigration, &nroots, &noldleaves, &oldLeaves, &oldRemote));
170300a1aa47SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfOverlap, NULL, &nleaves, NULL, NULL));
170400a1aa47SMatthew G. Knepley PetscCall(PetscMalloc1(nleaves, &newRemote));
170500a1aa47SMatthew G. Knepley /* oldRemote: original root point mapping to original leaf point
170600a1aa47SMatthew G. Knepley newRemote: original leaf point mapping to overlapped leaf point */
170700a1aa47SMatthew G. Knepley if (oldLeaves) {
170800a1aa47SMatthew G. Knepley /* After stratification, the migration remotes may not be in root (canonical) order, so we reorder using the leaf numbering */
170900a1aa47SMatthew G. Knepley PetscCall(PetscMalloc1(noldleaves, &permRemote));
171000a1aa47SMatthew G. Knepley for (PetscInt l = 0; l < noldleaves; ++l) permRemote[oldLeaves[l]] = oldRemote[l];
171100a1aa47SMatthew G. Knepley oldRemote = permRemote;
171200a1aa47SMatthew G. Knepley }
17136497c311SBarry Smith PetscCall(PetscSFBcastBegin(sfOverlap, MPIU_SF_NODE, oldRemote, newRemote, MPI_REPLACE));
17146497c311SBarry Smith PetscCall(PetscSFBcastEnd(sfOverlap, MPIU_SF_NODE, oldRemote, newRemote, MPI_REPLACE));
1715835f2295SStefano Zampini PetscCall(PetscFree(permRemote));
171600a1aa47SMatthew G. Knepley PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)sfOverlap), sfMigrationNew));
171700a1aa47SMatthew G. Knepley PetscCall(PetscSFSetGraph(*sfMigrationNew, nroots, nleaves, NULL, PETSC_OWN_POINTER, newRemote, PETSC_OWN_POINTER));
171800a1aa47SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
171900a1aa47SMatthew G. Knepley }
172000a1aa47SMatthew G. Knepley
17213b9d9b65SStefano Zampini /* For DG-like methods, the code below is equivalent (but faster) than calling
17223b9d9b65SStefano Zampini DMPlexCreateClosureIndex(dm,section) */
DMPlexCreateClosureIndex_CELL(DM dm,PetscSection section)17233b9d9b65SStefano Zampini static PetscErrorCode DMPlexCreateClosureIndex_CELL(DM dm, PetscSection section)
17243b9d9b65SStefano Zampini {
17253b9d9b65SStefano Zampini PetscSection clSection;
17263b9d9b65SStefano Zampini IS clPoints;
17273b9d9b65SStefano Zampini PetscInt pStart, pEnd, point;
17283b9d9b65SStefano Zampini PetscInt *closure, pos = 0;
17293b9d9b65SStefano Zampini
17303b9d9b65SStefano Zampini PetscFunctionBegin;
17313b9d9b65SStefano Zampini if (!section) PetscCall(DMGetLocalSection(dm, §ion));
17323b9d9b65SStefano Zampini PetscCall(DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd));
17333b9d9b65SStefano Zampini PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &clSection));
17343b9d9b65SStefano Zampini PetscCall(PetscSectionSetChart(clSection, pStart, pEnd));
17353b9d9b65SStefano Zampini PetscCall(PetscMalloc1((2 * (pEnd - pStart)), &closure));
17363b9d9b65SStefano Zampini for (point = pStart; point < pEnd; point++) {
17373b9d9b65SStefano Zampini PetscCall(PetscSectionSetDof(clSection, point, 2));
17383b9d9b65SStefano Zampini closure[pos++] = point; /* point */
17393b9d9b65SStefano Zampini closure[pos++] = 0; /* orientation */
17403b9d9b65SStefano Zampini }
17413b9d9b65SStefano Zampini PetscCall(PetscSectionSetUp(clSection));
17423b9d9b65SStefano Zampini PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 2 * (pEnd - pStart), closure, PETSC_OWN_POINTER, &clPoints));
17433b9d9b65SStefano Zampini PetscCall(PetscSectionSetClosureIndex(section, (PetscObject)dm, clSection, clPoints));
17443b9d9b65SStefano Zampini PetscCall(PetscSectionDestroy(&clSection));
17453b9d9b65SStefano Zampini PetscCall(ISDestroy(&clPoints));
17463b9d9b65SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS);
17473b9d9b65SStefano Zampini }
17483b9d9b65SStefano Zampini
DMPlexDistribute_Multistage(DM dm,PetscInt overlap,PetscSF * sf,DM * dmParallel)17493b9d9b65SStefano Zampini static PetscErrorCode DMPlexDistribute_Multistage(DM dm, PetscInt overlap, PetscSF *sf, DM *dmParallel)
17503b9d9b65SStefano Zampini {
17513b9d9b65SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)dm);
17523b9d9b65SStefano Zampini PetscPartitioner part;
17533b9d9b65SStefano Zampini PetscBool balance, printHeader;
17543b9d9b65SStefano Zampini PetscInt nl = 0;
17553b9d9b65SStefano Zampini
17563b9d9b65SStefano Zampini PetscFunctionBegin;
17573b9d9b65SStefano Zampini if (sf) *sf = NULL;
17583b9d9b65SStefano Zampini *dmParallel = NULL;
17593b9d9b65SStefano Zampini
17603b9d9b65SStefano Zampini PetscCall(DMPlexGetPartitioner(dm, &part));
17613b9d9b65SStefano Zampini printHeader = part->printHeader;
17623b9d9b65SStefano Zampini PetscCall(DMPlexGetPartitionBalance(dm, &balance));
17633b9d9b65SStefano Zampini PetscCall(PetscPartitionerSetUp(part));
17643b9d9b65SStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_DistributeMultistage, dm, 0, 0, 0));
17653b9d9b65SStefano Zampini PetscCall(PetscPartitionerMultistageGetStages_Multistage(part, &nl, NULL));
17663b9d9b65SStefano Zampini for (PetscInt l = 0; l < nl; l++) {
17673b9d9b65SStefano Zampini PetscInt ovl = (l < nl - 1) ? 0 : overlap;
17683b9d9b65SStefano Zampini PetscSF sfDist;
17693b9d9b65SStefano Zampini DM dmDist;
17703b9d9b65SStefano Zampini
17713b9d9b65SStefano Zampini PetscCall(DMPlexSetPartitionBalance(dm, balance));
17723b9d9b65SStefano Zampini PetscCall(DMViewFromOptions(dm, (PetscObject)part, "-petscpartitioner_multistage_dm_view"));
17733b9d9b65SStefano Zampini PetscCall(PetscPartitionerMultistageSetStage_Multistage(part, l, (PetscObject)dm));
17743b9d9b65SStefano Zampini PetscCall(DMPlexSetPartitioner(dm, part));
17753b9d9b65SStefano Zampini PetscCall(DMPlexDistribute(dm, ovl, &sfDist, &dmDist));
17763b9d9b65SStefano Zampini PetscCheck(dmDist, comm, PETSC_ERR_PLIB, "No distributed DM generated (stage %" PetscInt_FMT ")", l);
17773b9d9b65SStefano Zampini PetscCheck(sfDist, comm, PETSC_ERR_PLIB, "No SF generated (stage %" PetscInt_FMT ")", l);
17783b9d9b65SStefano Zampini part->printHeader = PETSC_FALSE;
17793b9d9b65SStefano Zampini
17803b9d9b65SStefano Zampini /* Propagate cell weights to the next level (if any, and if not the final dm) */
17813b9d9b65SStefano Zampini if (part->usevwgt && dm->localSection && l != nl - 1) {
17823b9d9b65SStefano Zampini PetscSection oldSection, newSection;
17833b9d9b65SStefano Zampini
17843b9d9b65SStefano Zampini PetscCall(DMGetLocalSection(dm, &oldSection));
17853b9d9b65SStefano Zampini PetscCall(DMGetLocalSection(dmDist, &newSection));
17863b9d9b65SStefano Zampini PetscCall(PetscSFDistributeSection(sfDist, oldSection, NULL, newSection));
17873b9d9b65SStefano Zampini PetscCall(DMPlexCreateClosureIndex_CELL(dmDist, newSection));
17883b9d9b65SStefano Zampini }
17893b9d9b65SStefano Zampini if (!sf) PetscCall(PetscSFDestroy(&sfDist));
17903b9d9b65SStefano Zampini if (l > 0) PetscCall(DMDestroy(&dm));
17913b9d9b65SStefano Zampini
17923b9d9b65SStefano Zampini if (sf && *sf) {
17933b9d9b65SStefano Zampini PetscSF sfA = *sf, sfB = sfDist;
17943b9d9b65SStefano Zampini PetscCall(PetscSFCompose(sfA, sfB, &sfDist));
17953b9d9b65SStefano Zampini PetscCall(PetscSFDestroy(&sfA));
17963b9d9b65SStefano Zampini PetscCall(PetscSFDestroy(&sfB));
17973b9d9b65SStefano Zampini }
17983b9d9b65SStefano Zampini
17993b9d9b65SStefano Zampini if (sf) *sf = sfDist;
18003b9d9b65SStefano Zampini dm = *dmParallel = dmDist;
18013b9d9b65SStefano Zampini }
18023b9d9b65SStefano Zampini PetscCall(PetscPartitionerMultistageSetStage_Multistage(part, 0, NULL)); /* reset */
18033b9d9b65SStefano Zampini PetscCall(PetscLogEventEnd(DMPLEX_DistributeMultistage, dm, 0, 0, 0));
18043b9d9b65SStefano Zampini part->printHeader = printHeader;
18053b9d9b65SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS);
18063b9d9b65SStefano Zampini }
18073b9d9b65SStefano Zampini
18085d83a8b1SBarry Smith /*@
180970034214SMatthew G. Knepley DMPlexDistribute - Distributes the mesh and any associated sections.
181070034214SMatthew G. Knepley
181120f4b53cSBarry Smith Collective
181270034214SMatthew G. Knepley
1813064ec1f3Sprj- Input Parameters:
181420f4b53cSBarry Smith + dm - The original `DMPLEX` object
181570034214SMatthew G. Knepley - overlap - The overlap of partitions, 0 is the default
181670034214SMatthew G. Knepley
1817064ec1f3Sprj- Output Parameters:
181820f4b53cSBarry Smith + sf - The `PetscSF` used for point distribution, or `NULL` if not needed
181920f4b53cSBarry Smith - dmParallel - The distributed `DMPLEX` object
182070034214SMatthew G. Knepley
182170034214SMatthew G. Knepley Level: intermediate
182270034214SMatthew G. Knepley
182320f4b53cSBarry Smith Note:
182420f4b53cSBarry Smith If the mesh was not distributed, the output `dmParallel` will be `NULL`.
182520f4b53cSBarry Smith
182620f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function
182720f4b53cSBarry Smith representation on the mesh.
182820f4b53cSBarry Smith
182920f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexGetOverlap()`
183070034214SMatthew G. Knepley @*/
DMPlexDistribute(DM dm,PetscInt overlap,PeOp PetscSF * sf,DM * dmParallel)1831ce78bad3SBarry Smith PetscErrorCode DMPlexDistribute(DM dm, PetscInt overlap, PeOp PetscSF *sf, DM *dmParallel)
1832d71ae5a4SJacob Faibussowitsch {
183370034214SMatthew G. Knepley MPI_Comm comm;
183415078cd4SMichael Lange PetscPartitioner partitioner;
1835f8987ae8SMichael Lange IS cellPart;
1836f8987ae8SMichael Lange PetscSection cellPartSection;
1837cf86098cSMatthew G. Knepley DM dmCoord;
1838f8987ae8SMichael Lange DMLabel lblPartition, lblMigration;
1839874ddda9SLisandro Dalcin PetscSF sfMigration, sfStratified, sfPoint;
18403b9d9b65SStefano Zampini PetscBool flg, balance, isms;
1841874ddda9SLisandro Dalcin PetscMPIInt rank, size;
184270034214SMatthew G. Knepley
184370034214SMatthew G. Knepley PetscFunctionBegin;
184470034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1845d5c515a1SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 2);
18464f572ea9SToby Isaac if (sf) PetscAssertPointer(sf, 3);
18474f572ea9SToby Isaac PetscAssertPointer(dmParallel, 4);
184870034214SMatthew G. Knepley
18490c86c063SLisandro Dalcin if (sf) *sf = NULL;
18500c86c063SLisandro Dalcin *dmParallel = NULL;
18519566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
18529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
18539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
18543ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS);
185570034214SMatthew G. Knepley
18563b9d9b65SStefano Zampini /* Handle multistage partitioner */
18573b9d9b65SStefano Zampini PetscCall(DMPlexGetPartitioner(dm, &partitioner));
18583b9d9b65SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)partitioner, PETSCPARTITIONERMULTISTAGE, &isms));
18593b9d9b65SStefano Zampini if (isms) {
18603b9d9b65SStefano Zampini PetscObject stagedm;
18613b9d9b65SStefano Zampini
18623b9d9b65SStefano Zampini PetscCall(PetscPartitionerMultistageGetStage_Multistage(partitioner, NULL, &stagedm));
18633b9d9b65SStefano Zampini if (!stagedm) { /* No stage dm present, start the multistage algorithm */
18643b9d9b65SStefano Zampini PetscCall(DMPlexDistribute_Multistage(dm, overlap, sf, dmParallel));
18653b9d9b65SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS);
18663b9d9b65SStefano Zampini }
18673b9d9b65SStefano Zampini }
18689566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Distribute, dm, 0, 0, 0));
186915078cd4SMichael Lange /* Create cell partition */
18709566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0));
18719566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &cellPartSection));
18729566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDMPlexPartition(partitioner, dm, NULL, cellPartSection, &cellPart));
18739566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartSelf, dm, 0, 0, 0));
1874f8987ae8SMichael Lange {
1875f8987ae8SMichael Lange /* Convert partition to DMLabel */
1876825f8a23SLisandro Dalcin IS is;
1877825f8a23SLisandro Dalcin PetscHSetI ht;
1878f8987ae8SMichael Lange const PetscInt *points;
18798e330a33SStefano Zampini PetscInt *iranks;
18808e330a33SStefano Zampini PetscInt pStart, pEnd, proc, npoints, poff = 0, nranks;
1881825f8a23SLisandro Dalcin
18829566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point Partition", &lblPartition));
1883825f8a23SLisandro Dalcin /* Preallocate strata */
18849566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht));
18859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd));
1886825f8a23SLisandro Dalcin for (proc = pStart; proc < pEnd; proc++) {
18879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints));
18889566063dSJacob Faibussowitsch if (npoints) PetscCall(PetscHSetIAdd(ht, proc));
1889825f8a23SLisandro Dalcin }
18909566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ht, &nranks));
18919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nranks, &iranks));
18929566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ht, &poff, iranks));
18939566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht));
18949566063dSJacob Faibussowitsch PetscCall(DMLabelAddStrata(lblPartition, nranks, iranks));
18959566063dSJacob Faibussowitsch PetscCall(PetscFree(iranks));
1896825f8a23SLisandro Dalcin /* Inline DMPlexPartitionLabelClosure() */
18979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellPart, &points));
18989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd));
1899f8987ae8SMichael Lange for (proc = pStart; proc < pEnd; proc++) {
19009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints));
1901825f8a23SLisandro Dalcin if (!npoints) continue;
19029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellPartSection, proc, &poff));
19039566063dSJacob Faibussowitsch PetscCall(DMPlexClosurePoints_Private(dm, npoints, points + poff, &is));
19049566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(lblPartition, proc, is));
19059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is));
1906f8987ae8SMichael Lange }
19079566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellPart, &points));
1908f8987ae8SMichael Lange }
19099566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartSelf, dm, 0, 0, 0));
19106e203dd9SStefano Zampini
19119566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point migration", &lblMigration));
19129566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelInvert(dm, lblPartition, NULL, lblMigration));
19133ac0285dSStefano Zampini PetscCall(DMPlexPartitionLabelCreateSF(dm, lblMigration, PETSC_TRUE, &sfMigration));
19149566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, sfMigration, &sfStratified));
19159566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration));
191643f7d02bSMichael Lange sfMigration = sfStratified;
19179566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sfMigration));
19189566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0));
19199566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-partition_view", &flg));
192070034214SMatthew G. Knepley if (flg) {
19219566063dSJacob Faibussowitsch PetscCall(DMLabelView(lblPartition, PETSC_VIEWER_STDOUT_(comm)));
19229566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfMigration, PETSC_VIEWER_STDOUT_(comm)));
192370034214SMatthew G. Knepley }
1924f8987ae8SMichael Lange
192515078cd4SMichael Lange /* Create non-overlapping parallel DM and migrate internal data */
19269566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, dmParallel));
19279566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*dmParallel, "Parallel Mesh"));
19289566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(dm, sfMigration, *dmParallel));
192970034214SMatthew G. Knepley
1930a157612eSMichael Lange /* Build the point SF without overlap */
19319566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitionBalance(dm, &balance));
19329566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitionBalance(*dmParallel, balance));
19339566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*dmParallel, sfMigration, PETSC_TRUE, &sfPoint));
19349566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*dmParallel, sfPoint));
19355f06a3ddSJed Brown PetscCall(DMPlexMigrateIsoperiodicFaceSF_Internal(dm, *dmParallel, sfMigration));
19369566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dmParallel, &dmCoord));
19379566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint));
19389566063dSJacob Faibussowitsch if (flg) PetscCall(PetscSFView(sfPoint, NULL));
193970034214SMatthew G. Knepley
1940a157612eSMichael Lange if (overlap > 0) {
194115078cd4SMichael Lange DM dmOverlap;
194215078cd4SMichael Lange PetscSF sfOverlap, sfOverlapPoint;
1943524e35f8SStefano Zampini
1944a157612eSMichael Lange /* Add the partition overlap to the distributed DM */
19459566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeOverlap(*dmParallel, overlap, &sfOverlap, &dmOverlap));
19469566063dSJacob Faibussowitsch PetscCall(DMDestroy(dmParallel));
1947a157612eSMichael Lange *dmParallel = dmOverlap;
1948c389ea9fSToby Isaac if (flg) {
19499566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Overlap Migration SF:\n"));
19509566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfOverlap, NULL));
1951c389ea9fSToby Isaac }
195243331d4aSMichael Lange
1953f8987ae8SMichael Lange /* Re-map the migration SF to establish the full migration pattern */
195400a1aa47SMatthew G. Knepley PetscCall(DMPlexRemapMigrationSF(sfOverlap, sfMigration, &sfOverlapPoint));
19559566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfOverlap));
19569566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration));
195715078cd4SMichael Lange sfMigration = sfOverlapPoint;
1958c389ea9fSToby Isaac }
1959bf5244c7SMatthew G. Knepley /* Cleanup Partition */
19609566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblPartition));
19619566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblMigration));
19629566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cellPartSection));
19639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellPart));
196412a88998SMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *dmParallel));
196512a88998SMatthew G. Knepley // Create sfNatural, need discretization information
19669566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *dmParallel));
19675d2873a6SJames Wright if (dm->localSection) {
19685d2873a6SJames Wright PetscSection psection;
19695d2873a6SJames Wright PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &psection));
19705d2873a6SJames Wright PetscCall(PetscSFDistributeSection(sfMigration, dm->localSection, NULL, psection));
19715d2873a6SJames Wright PetscCall(DMSetLocalSection(*dmParallel, psection));
19725d2873a6SJames Wright PetscCall(PetscSectionDestroy(&psection));
19735d2873a6SJames Wright }
197466fe0bfeSMatthew G. Knepley if (dm->useNatural) {
197566fe0bfeSMatthew G. Knepley PetscSection section;
197666fe0bfeSMatthew G. Knepley
1977fc6a3818SBlaise Bourdin PetscCall(DMSetUseNatural(*dmParallel, PETSC_TRUE));
1978fc6a3818SBlaise Bourdin PetscCall(DMGetLocalSection(dm, §ion));
1979fc6a3818SBlaise Bourdin
198016635c05SJames Wright /* If DM has useNatural = PETSC_TRUE, but no sfNatural is set, the DM's Section is considered natural */
19818aee0f92SAlexis Marboeuf /* sfMigration and sfNatural are respectively the point and dofs SFs mapping to this natural DM */
1982fc6a3818SBlaise Bourdin /* Compose with a previous sfNatural if present */
1983fc6a3818SBlaise Bourdin if (dm->sfNatural) {
198416635c05SJames Wright PetscCall(DMPlexMigrateGlobalToNaturalSF(dm, *dmParallel, dm->sfNatural, sfMigration, &(*dmParallel)->sfNatural));
1985fc6a3818SBlaise Bourdin } else {
1986fc6a3818SBlaise Bourdin PetscCall(DMPlexCreateGlobalToNaturalSF(*dmParallel, section, sfMigration, &(*dmParallel)->sfNatural));
1987fc6a3818SBlaise Bourdin }
19888aee0f92SAlexis Marboeuf /* Compose with a previous sfMigration if present */
19898aee0f92SAlexis Marboeuf if (dm->sfMigration) {
19908aee0f92SAlexis Marboeuf PetscSF naturalPointSF;
19918aee0f92SAlexis Marboeuf
19928aee0f92SAlexis Marboeuf PetscCall(PetscSFCompose(dm->sfMigration, sfMigration, &naturalPointSF));
19938aee0f92SAlexis Marboeuf PetscCall(PetscSFDestroy(&sfMigration));
19948aee0f92SAlexis Marboeuf sfMigration = naturalPointSF;
19958aee0f92SAlexis Marboeuf }
199666fe0bfeSMatthew G. Knepley }
1997721cbd76SMatthew G. Knepley /* Cleanup */
19989371c9d4SSatish Balay if (sf) {
19999371c9d4SSatish Balay *sf = sfMigration;
20009371c9d4SSatish Balay } else PetscCall(PetscSFDestroy(&sfMigration));
20019566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint));
20029566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Distribute, dm, 0, 0, 0));
20033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
200470034214SMatthew G. Knepley }
2005a157612eSMichael Lange
DMPlexDistributeOverlap_Internal(DM dm,PetscInt overlap,MPI_Comm newcomm,const char * ovlboundary,PetscSF * sf,DM * dmOverlap)2006907a3e9cSStefano Zampini PetscErrorCode DMPlexDistributeOverlap_Internal(DM dm, PetscInt overlap, MPI_Comm newcomm, const char *ovlboundary, PetscSF *sf, DM *dmOverlap)
2007907a3e9cSStefano Zampini {
2008907a3e9cSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data;
2009907a3e9cSStefano Zampini MPI_Comm comm;
2010907a3e9cSStefano Zampini PetscMPIInt size, rank;
2011907a3e9cSStefano Zampini PetscSection rootSection, leafSection;
2012907a3e9cSStefano Zampini IS rootrank, leafrank;
2013907a3e9cSStefano Zampini DM dmCoord;
2014907a3e9cSStefano Zampini DMLabel lblOverlap;
2015907a3e9cSStefano Zampini PetscSF sfOverlap, sfStratified, sfPoint;
2016907a3e9cSStefano Zampini PetscBool clear_ovlboundary;
2017907a3e9cSStefano Zampini
2018907a3e9cSStefano Zampini PetscFunctionBegin;
2019907a3e9cSStefano Zampini if (sf) *sf = NULL;
2020907a3e9cSStefano Zampini *dmOverlap = NULL;
2021907a3e9cSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
2022907a3e9cSStefano Zampini PetscCallMPI(MPI_Comm_size(comm, &size));
2023907a3e9cSStefano Zampini PetscCallMPI(MPI_Comm_rank(comm, &rank));
2024907a3e9cSStefano Zampini if (size == 1) PetscFunctionReturn(PETSC_SUCCESS);
2025907a3e9cSStefano Zampini {
2026907a3e9cSStefano Zampini // We need to get options for the _already_distributed mesh, so it must be done here
2027907a3e9cSStefano Zampini PetscInt overlap;
2028907a3e9cSStefano Zampini const char *prefix;
2029907a3e9cSStefano Zampini char oldPrefix[PETSC_MAX_PATH_LEN];
2030907a3e9cSStefano Zampini
2031907a3e9cSStefano Zampini oldPrefix[0] = '\0';
2032907a3e9cSStefano Zampini PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
2033907a3e9cSStefano Zampini PetscCall(PetscStrncpy(oldPrefix, prefix, sizeof(oldPrefix)));
2034907a3e9cSStefano Zampini PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, "dist_"));
2035907a3e9cSStefano Zampini PetscCall(DMPlexGetOverlap(dm, &overlap));
2036907a3e9cSStefano Zampini PetscObjectOptionsBegin((PetscObject)dm);
2037907a3e9cSStefano Zampini PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap));
2038907a3e9cSStefano Zampini PetscOptionsEnd();
2039907a3e9cSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix[0] == '\0' ? NULL : oldPrefix));
2040907a3e9cSStefano Zampini }
2041907a3e9cSStefano Zampini if (ovlboundary) {
2042907a3e9cSStefano Zampini PetscBool flg;
2043907a3e9cSStefano Zampini PetscCall(DMHasLabel(dm, ovlboundary, &flg));
2044907a3e9cSStefano Zampini if (!flg) {
2045907a3e9cSStefano Zampini DMLabel label;
2046907a3e9cSStefano Zampini
2047907a3e9cSStefano Zampini PetscCall(DMCreateLabel(dm, ovlboundary));
2048907a3e9cSStefano Zampini PetscCall(DMGetLabel(dm, ovlboundary, &label));
2049907a3e9cSStefano Zampini PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label));
2050907a3e9cSStefano Zampini clear_ovlboundary = PETSC_TRUE;
2051907a3e9cSStefano Zampini }
2052907a3e9cSStefano Zampini }
2053907a3e9cSStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_DistributeOverlap, dm, 0, 0, 0));
2054907a3e9cSStefano Zampini /* Compute point overlap with neighbouring processes on the distributed DM */
2055907a3e9cSStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0));
2056907a3e9cSStefano Zampini PetscCall(PetscSectionCreate(newcomm, &rootSection));
2057907a3e9cSStefano Zampini PetscCall(PetscSectionCreate(newcomm, &leafSection));
2058907a3e9cSStefano Zampini PetscCall(DMPlexDistributeOwnership(dm, rootSection, &rootrank, leafSection, &leafrank));
2059907a3e9cSStefano Zampini if (mesh->numOvLabels) PetscCall(DMPlexCreateOverlapLabelFromLabels(dm, mesh->numOvLabels, mesh->ovLabels, mesh->ovValues, mesh->numOvExLabels, mesh->ovExLabels, mesh->ovExValues, rootSection, rootrank, leafSection, leafrank, &lblOverlap));
2060907a3e9cSStefano Zampini else PetscCall(DMPlexCreateOverlapLabel(dm, overlap, rootSection, rootrank, leafSection, leafrank, &lblOverlap));
2061907a3e9cSStefano Zampini /* Convert overlap label to stratified migration SF */
20623ac0285dSStefano Zampini PetscCall(DMPlexPartitionLabelCreateSF(dm, lblOverlap, PETSC_FALSE, &sfOverlap));
2063907a3e9cSStefano Zampini PetscCall(DMPlexStratifyMigrationSF(dm, sfOverlap, &sfStratified));
2064907a3e9cSStefano Zampini PetscCall(PetscSFDestroy(&sfOverlap));
2065907a3e9cSStefano Zampini sfOverlap = sfStratified;
2066907a3e9cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)sfOverlap, "Overlap SF"));
2067907a3e9cSStefano Zampini PetscCall(PetscSFSetFromOptions(sfOverlap));
2068907a3e9cSStefano Zampini
2069907a3e9cSStefano Zampini PetscCall(PetscSectionDestroy(&rootSection));
2070907a3e9cSStefano Zampini PetscCall(PetscSectionDestroy(&leafSection));
2071907a3e9cSStefano Zampini PetscCall(ISDestroy(&rootrank));
2072907a3e9cSStefano Zampini PetscCall(ISDestroy(&leafrank));
2073907a3e9cSStefano Zampini PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0));
2074907a3e9cSStefano Zampini
2075907a3e9cSStefano Zampini /* Build the overlapping DM */
2076907a3e9cSStefano Zampini PetscCall(DMPlexCreate(newcomm, dmOverlap));
2077907a3e9cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*dmOverlap, "Parallel Mesh"));
2078907a3e9cSStefano Zampini PetscCall(DMPlexMigrate(dm, sfOverlap, *dmOverlap));
2079907a3e9cSStefano Zampini /* Store the overlap in the new DM */
2080907a3e9cSStefano Zampini PetscCall(DMPlexSetOverlap_Plex(*dmOverlap, dm, overlap));
2081907a3e9cSStefano Zampini /* Build the new point SF */
2082907a3e9cSStefano Zampini PetscCall(DMPlexCreatePointSF(*dmOverlap, sfOverlap, PETSC_FALSE, &sfPoint));
2083907a3e9cSStefano Zampini PetscCall(DMSetPointSF(*dmOverlap, sfPoint));
2084907a3e9cSStefano Zampini PetscCall(DMGetCoordinateDM(*dmOverlap, &dmCoord));
2085907a3e9cSStefano Zampini if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint));
2086907a3e9cSStefano Zampini PetscCall(DMGetCellCoordinateDM(*dmOverlap, &dmCoord));
2087907a3e9cSStefano Zampini if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint));
2088907a3e9cSStefano Zampini PetscCall(PetscSFDestroy(&sfPoint));
2089907a3e9cSStefano Zampini PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *dmOverlap));
2090907a3e9cSStefano Zampini /* TODO: labels stored inside the DS for regions should be handled here */
2091907a3e9cSStefano Zampini PetscCall(DMCopyDisc(dm, *dmOverlap));
2092907a3e9cSStefano Zampini /* Cleanup overlap partition */
2093907a3e9cSStefano Zampini PetscCall(DMLabelDestroy(&lblOverlap));
2094907a3e9cSStefano Zampini if (sf) *sf = sfOverlap;
2095907a3e9cSStefano Zampini else PetscCall(PetscSFDestroy(&sfOverlap));
2096907a3e9cSStefano Zampini if (ovlboundary) {
2097907a3e9cSStefano Zampini DMLabel label;
2098907a3e9cSStefano Zampini PetscBool flg;
2099907a3e9cSStefano Zampini
2100907a3e9cSStefano Zampini if (clear_ovlboundary) PetscCall(DMRemoveLabel(dm, ovlboundary, NULL));
2101907a3e9cSStefano Zampini PetscCall(DMHasLabel(*dmOverlap, ovlboundary, &flg));
210200045ab3SPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing %s label", ovlboundary);
2103907a3e9cSStefano Zampini PetscCall(DMGetLabel(*dmOverlap, ovlboundary, &label));
2104907a3e9cSStefano Zampini PetscCall(DMPlexMarkBoundaryFaces_Internal(*dmOverlap, 1, 0, label, PETSC_TRUE));
2105907a3e9cSStefano Zampini }
2106907a3e9cSStefano Zampini PetscCall(PetscLogEventEnd(DMPLEX_DistributeOverlap, dm, 0, 0, 0));
2107907a3e9cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS);
2108907a3e9cSStefano Zampini }
2109907a3e9cSStefano Zampini
21105d83a8b1SBarry Smith /*@
211120f4b53cSBarry Smith DMPlexDistributeOverlap - Add partition overlap to a distributed non-overlapping `DM`.
2112a157612eSMichael Lange
211320f4b53cSBarry Smith Collective
2114a157612eSMichael Lange
2115064ec1f3Sprj- Input Parameters:
211620f4b53cSBarry Smith + dm - The non-overlapping distributed `DMPLEX` object
211757fe9a49SVaclav Hapla - overlap - The overlap of partitions (the same on all ranks)
2118a157612eSMichael Lange
2119064ec1f3Sprj- Output Parameters:
2120f13dfd9eSBarry Smith + sf - The `PetscSF` used for point distribution, or pass `NULL` if not needed
2121f13dfd9eSBarry Smith - dmOverlap - The overlapping distributed `DMPLEX` object
2122a157612eSMichael Lange
2123c506a872SMatthew G. Knepley Options Database Keys:
2124c506a872SMatthew G. Knepley + -dm_plex_overlap_labels <name1,name2,...> - List of overlap label names
2125c506a872SMatthew G. Knepley . -dm_plex_overlap_values <int1,int2,...> - List of overlap label values
2126c506a872SMatthew G. Knepley . -dm_plex_overlap_exclude_label <name> - Label used to exclude points from overlap
2127c506a872SMatthew G. Knepley - -dm_plex_overlap_exclude_value <int> - Label value used to exclude points from overlap
2128c506a872SMatthew G. Knepley
2129dccdeccaSVaclav Hapla Level: advanced
2130a157612eSMichael Lange
213120f4b53cSBarry Smith Notes:
213220f4b53cSBarry Smith If the mesh was not distributed, the return value is `NULL`.
213320f4b53cSBarry Smith
213420f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function
213520f4b53cSBarry Smith representation on the mesh.
213620f4b53cSBarry Smith
213720f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMPlexCreateOverlapLabel()`, `DMPlexGetOverlap()`
2138a157612eSMichael Lange @*/
DMPlexDistributeOverlap(DM dm,PetscInt overlap,PeOp PetscSF * sf,DM * dmOverlap)2139ce78bad3SBarry Smith PetscErrorCode DMPlexDistributeOverlap(DM dm, PetscInt overlap, PeOp PetscSF *sf, DM *dmOverlap)
2140d71ae5a4SJacob Faibussowitsch {
2141a157612eSMichael Lange PetscFunctionBegin;
2142a157612eSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
214357fe9a49SVaclav Hapla PetscValidLogicalCollectiveInt(dm, overlap, 2);
21444f572ea9SToby Isaac if (sf) PetscAssertPointer(sf, 3);
21454f572ea9SToby Isaac PetscAssertPointer(dmOverlap, 4);
2146907a3e9cSStefano Zampini PetscCall(DMPlexDistributeOverlap_Internal(dm, overlap, PetscObjectComm((PetscObject)dm), NULL, sf, dmOverlap));
21473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2148a157612eSMichael Lange }
21496462276dSToby Isaac
DMPlexGetOverlap_Plex(DM dm,PetscInt * overlap)2150d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap_Plex(DM dm, PetscInt *overlap)
2151d71ae5a4SJacob Faibussowitsch {
2152cb54e036SVaclav Hapla DM_Plex *mesh = (DM_Plex *)dm->data;
2153cb54e036SVaclav Hapla
2154cb54e036SVaclav Hapla PetscFunctionBegin;
2155cb54e036SVaclav Hapla *overlap = mesh->overlap;
21563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2157cb54e036SVaclav Hapla }
2158cb54e036SVaclav Hapla
DMPlexSetOverlap_Plex(DM dm,DM dmSrc,PetscInt overlap)2159d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap_Plex(DM dm, DM dmSrc, PetscInt overlap)
2160d71ae5a4SJacob Faibussowitsch {
216160667520SVaclav Hapla DM_Plex *mesh = NULL;
216260667520SVaclav Hapla DM_Plex *meshSrc = NULL;
216360667520SVaclav Hapla
216460667520SVaclav Hapla PetscFunctionBegin;
216560667520SVaclav Hapla PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX);
216660667520SVaclav Hapla mesh = (DM_Plex *)dm->data;
216760667520SVaclav Hapla if (dmSrc) {
216860667520SVaclav Hapla PetscValidHeaderSpecificType(dmSrc, DM_CLASSID, 2, DMPLEX);
216960667520SVaclav Hapla meshSrc = (DM_Plex *)dmSrc->data;
21709ed9361bSToby Isaac mesh->overlap = meshSrc->overlap;
21719ed9361bSToby Isaac } else {
21729ed9361bSToby Isaac mesh->overlap = 0;
217360667520SVaclav Hapla }
21749ed9361bSToby Isaac mesh->overlap += overlap;
21753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
217660667520SVaclav Hapla }
217760667520SVaclav Hapla
2178cb54e036SVaclav Hapla /*@
2179c506a872SMatthew G. Knepley DMPlexGetOverlap - Get the width of the cell overlap
2180cb54e036SVaclav Hapla
218120f4b53cSBarry Smith Not Collective
2182cb54e036SVaclav Hapla
2183cb54e036SVaclav Hapla Input Parameter:
218420f4b53cSBarry Smith . dm - The `DM`
2185cb54e036SVaclav Hapla
2186064ec1f3Sprj- Output Parameter:
2187c506a872SMatthew G. Knepley . overlap - the width of the cell overlap
2188cb54e036SVaclav Hapla
2189cb54e036SVaclav Hapla Level: intermediate
2190cb54e036SVaclav Hapla
219120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexSetOverlap()`, `DMPlexDistribute()`
2192cb54e036SVaclav Hapla @*/
DMPlexGetOverlap(DM dm,PetscInt * overlap)2193d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap(DM dm, PetscInt *overlap)
2194d71ae5a4SJacob Faibussowitsch {
2195cb54e036SVaclav Hapla PetscFunctionBegin;
2196cb54e036SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21974f572ea9SToby Isaac PetscAssertPointer(overlap, 2);
2198cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexGetOverlap_C", (DM, PetscInt *), (dm, overlap));
21993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2200cb54e036SVaclav Hapla }
2201cb54e036SVaclav Hapla
2202c506a872SMatthew G. Knepley /*@
2203c506a872SMatthew G. Knepley DMPlexSetOverlap - Set the width of the cell overlap
2204c506a872SMatthew G. Knepley
220520f4b53cSBarry Smith Logically Collective
2206c506a872SMatthew G. Knepley
2207c506a872SMatthew G. Knepley Input Parameters:
220820f4b53cSBarry Smith + dm - The `DM`
220920f4b53cSBarry Smith . dmSrc - The `DM` that produced this one, or `NULL`
2210c506a872SMatthew G. Knepley - overlap - the width of the cell overlap
2211c506a872SMatthew G. Knepley
2212c506a872SMatthew G. Knepley Level: intermediate
2213c506a872SMatthew G. Knepley
221420f4b53cSBarry Smith Note:
221520f4b53cSBarry Smith The overlap from `dmSrc` is added to `dm`
221620f4b53cSBarry Smith
221720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexGetOverlap()`, `DMPlexDistribute()`
2218c506a872SMatthew G. Knepley @*/
DMPlexSetOverlap(DM dm,DM dmSrc,PetscInt overlap)2219d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap(DM dm, DM dmSrc, PetscInt overlap)
2220d71ae5a4SJacob Faibussowitsch {
2221c506a872SMatthew G. Knepley PetscFunctionBegin;
2222c506a872SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2223c506a872SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 3);
2224c506a872SMatthew G. Knepley PetscTryMethod(dm, "DMPlexSetOverlap_C", (DM, DM, PetscInt), (dm, dmSrc, overlap));
22253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2226c506a872SMatthew G. Knepley }
2227c506a872SMatthew G. Knepley
DMPlexDistributeSetDefault_Plex(DM dm,PetscBool dist)2228d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault_Plex(DM dm, PetscBool dist)
2229d71ae5a4SJacob Faibussowitsch {
2230e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
2231e600fa54SMatthew G. Knepley
2232e600fa54SMatthew G. Knepley PetscFunctionBegin;
2233e600fa54SMatthew G. Knepley mesh->distDefault = dist;
22343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2235e600fa54SMatthew G. Knepley }
2236e600fa54SMatthew G. Knepley
2237e600fa54SMatthew G. Knepley /*@
223820f4b53cSBarry Smith DMPlexDistributeSetDefault - Set flag indicating whether the `DM` should be distributed by default
2239e600fa54SMatthew G. Knepley
224020f4b53cSBarry Smith Logically Collective
2241e600fa54SMatthew G. Knepley
2242e600fa54SMatthew G. Knepley Input Parameters:
224320f4b53cSBarry Smith + dm - The `DM`
2244e600fa54SMatthew G. Knepley - dist - Flag for distribution
2245e600fa54SMatthew G. Knepley
2246e600fa54SMatthew G. Knepley Level: intermediate
2247e600fa54SMatthew G. Knepley
224820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributeGetDefault()`, `DMPlexDistribute()`
2249e600fa54SMatthew G. Knepley @*/
DMPlexDistributeSetDefault(DM dm,PetscBool dist)2250d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault(DM dm, PetscBool dist)
2251d71ae5a4SJacob Faibussowitsch {
2252e600fa54SMatthew G. Knepley PetscFunctionBegin;
2253e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2254e600fa54SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, dist, 2);
2255cac4c232SBarry Smith PetscTryMethod(dm, "DMPlexDistributeSetDefault_C", (DM, PetscBool), (dm, dist));
22563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2257e600fa54SMatthew G. Knepley }
2258e600fa54SMatthew G. Knepley
DMPlexDistributeGetDefault_Plex(DM dm,PetscBool * dist)2259d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault_Plex(DM dm, PetscBool *dist)
2260d71ae5a4SJacob Faibussowitsch {
2261e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
2262e600fa54SMatthew G. Knepley
2263e600fa54SMatthew G. Knepley PetscFunctionBegin;
2264e600fa54SMatthew G. Knepley *dist = mesh->distDefault;
22653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2266e600fa54SMatthew G. Knepley }
2267e600fa54SMatthew G. Knepley
2268e600fa54SMatthew G. Knepley /*@
226920f4b53cSBarry Smith DMPlexDistributeGetDefault - Get flag indicating whether the `DM` should be distributed by default
2270e600fa54SMatthew G. Knepley
227120f4b53cSBarry Smith Not Collective
2272e600fa54SMatthew G. Knepley
2273e600fa54SMatthew G. Knepley Input Parameter:
227420f4b53cSBarry Smith . dm - The `DM`
2275e600fa54SMatthew G. Knepley
2276e600fa54SMatthew G. Knepley Output Parameter:
2277e600fa54SMatthew G. Knepley . dist - Flag for distribution
2278e600fa54SMatthew G. Knepley
2279e600fa54SMatthew G. Knepley Level: intermediate
2280e600fa54SMatthew G. Knepley
228120f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexDistributeSetDefault()`, `DMPlexDistribute()`
2282e600fa54SMatthew G. Knepley @*/
DMPlexDistributeGetDefault(DM dm,PetscBool * dist)2283d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault(DM dm, PetscBool *dist)
2284d71ae5a4SJacob Faibussowitsch {
2285e600fa54SMatthew G. Knepley PetscFunctionBegin;
2286e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22874f572ea9SToby Isaac PetscAssertPointer(dist, 2);
2288cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexDistributeGetDefault_C", (DM, PetscBool *), (dm, dist));
22893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2290e600fa54SMatthew G. Knepley }
2291e600fa54SMatthew G. Knepley
2292ce78bad3SBarry Smith /*@
229320f4b53cSBarry Smith DMPlexGetGatherDM - Get a copy of the `DMPLEX` that gathers all points on the
22946462276dSToby Isaac root process of the original's communicator.
22956462276dSToby Isaac
229620f4b53cSBarry Smith Collective
229783655b49SVáclav Hapla
2298064ec1f3Sprj- Input Parameter:
229920f4b53cSBarry Smith . dm - the original `DMPLEX` object
23006462276dSToby Isaac
23016462276dSToby Isaac Output Parameters:
230220f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional)
230320f4b53cSBarry Smith - gatherMesh - the gathered `DM` object, or `NULL`
23046462276dSToby Isaac
23056462276dSToby Isaac Level: intermediate
23066462276dSToby Isaac
230720f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `PetscSF`, `DMPlexDistribute()`, `DMPlexGetRedundantDM()`
23086462276dSToby Isaac @*/
DMPlexGetGatherDM(DM dm,PetscSF * sf,PeOp DM * gatherMesh)2309ce78bad3SBarry Smith PetscErrorCode DMPlexGetGatherDM(DM dm, PetscSF *sf, PeOp DM *gatherMesh)
2310d71ae5a4SJacob Faibussowitsch {
23116462276dSToby Isaac MPI_Comm comm;
23126462276dSToby Isaac PetscMPIInt size;
23136462276dSToby Isaac PetscPartitioner oldPart, gatherPart;
23146462276dSToby Isaac
23156462276dSToby Isaac PetscFunctionBegin;
23166462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23174f572ea9SToby Isaac PetscAssertPointer(gatherMesh, 3);
23180c86c063SLisandro Dalcin *gatherMesh = NULL;
2319a13df41bSStefano Zampini if (sf) *sf = NULL;
23206462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm);
23219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
23223ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS);
23239566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &oldPart));
23249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)oldPart));
23259566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(comm, &gatherPart));
23269566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetType(gatherPart, PETSCPARTITIONERGATHER));
23279566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, gatherPart));
23289566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, sf, gatherMesh));
2329a13df41bSStefano Zampini
23309566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, oldPart));
23319566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&gatherPart));
23329566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&oldPart));
23333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
23346462276dSToby Isaac }
23356462276dSToby Isaac
2336ce78bad3SBarry Smith /*@
233720f4b53cSBarry Smith DMPlexGetRedundantDM - Get a copy of the `DMPLEX` that is completely copied on each process.
23386462276dSToby Isaac
233920f4b53cSBarry Smith Collective
234083655b49SVáclav Hapla
2341064ec1f3Sprj- Input Parameter:
234220f4b53cSBarry Smith . dm - the original `DMPLEX` object
23436462276dSToby Isaac
23446462276dSToby Isaac Output Parameters:
234520f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional)
234620f4b53cSBarry Smith - redundantMesh - the redundant `DM` object, or `NULL`
23476462276dSToby Isaac
23486462276dSToby Isaac Level: intermediate
23496462276dSToby Isaac
235060225df5SJacob Faibussowitsch .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetGatherDM()`
23516462276dSToby Isaac @*/
DMPlexGetRedundantDM(DM dm,PetscSF * sf,PeOp DM * redundantMesh)2352ce78bad3SBarry Smith PetscErrorCode DMPlexGetRedundantDM(DM dm, PetscSF *sf, PeOp DM *redundantMesh)
2353d71ae5a4SJacob Faibussowitsch {
23546462276dSToby Isaac MPI_Comm comm;
23556462276dSToby Isaac PetscMPIInt size, rank;
23566462276dSToby Isaac PetscInt pStart, pEnd, p;
23576462276dSToby Isaac PetscInt numPoints = -1;
2358a13df41bSStefano Zampini PetscSF migrationSF, sfPoint, gatherSF;
23596462276dSToby Isaac DM gatherDM, dmCoord;
23606462276dSToby Isaac PetscSFNode *points;
23616462276dSToby Isaac
23626462276dSToby Isaac PetscFunctionBegin;
23636462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23644f572ea9SToby Isaac PetscAssertPointer(redundantMesh, 3);
23650c86c063SLisandro Dalcin *redundantMesh = NULL;
23666462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm);
23679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
236868dbc166SMatthew G. Knepley if (size == 1) {
23699566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm));
237068dbc166SMatthew G. Knepley *redundantMesh = dm;
2371a13df41bSStefano Zampini if (sf) *sf = NULL;
23723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
237368dbc166SMatthew G. Knepley }
23749566063dSJacob Faibussowitsch PetscCall(DMPlexGetGatherDM(dm, &gatherSF, &gatherDM));
23753ba16761SJacob Faibussowitsch if (!gatherDM) PetscFunctionReturn(PETSC_SUCCESS);
23769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
23779566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(gatherDM, &pStart, &pEnd));
23786462276dSToby Isaac numPoints = pEnd - pStart;
23799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numPoints, 1, MPIU_INT, 0, comm));
23809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &points));
23819566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &migrationSF));
23826462276dSToby Isaac for (p = 0; p < numPoints; p++) {
23836462276dSToby Isaac points[p].index = p;
23846462276dSToby Isaac points[p].rank = 0;
23856462276dSToby Isaac }
23869566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(migrationSF, pEnd - pStart, numPoints, NULL, PETSC_OWN_POINTER, points, PETSC_OWN_POINTER));
23879566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, redundantMesh));
23889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*redundantMesh, "Redundant Mesh"));
23899566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(gatherDM, migrationSF, *redundantMesh));
23902e28cf0cSVaclav Hapla /* This is to express that all point are in overlap */
23911690c2aeSBarry Smith PetscCall(DMPlexSetOverlap_Plex(*redundantMesh, NULL, PETSC_INT_MAX));
23929566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*redundantMesh, migrationSF, PETSC_FALSE, &sfPoint));
23939566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*redundantMesh, sfPoint));
23949566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*redundantMesh, &dmCoord));
23959566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint));
23969566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint));
2397a13df41bSStefano Zampini if (sf) {
2398a13df41bSStefano Zampini PetscSF tsf;
2399a13df41bSStefano Zampini
24009566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(gatherSF, migrationSF, &tsf));
24019566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, tsf, sf));
24029566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&tsf));
2403a13df41bSStefano Zampini }
24049566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&migrationSF));
24059566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&gatherSF));
24069566063dSJacob Faibussowitsch PetscCall(DMDestroy(&gatherDM));
24079566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *redundantMesh));
24085de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *redundantMesh));
24093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
24106462276dSToby Isaac }
24115fa78c88SVaclav Hapla
24125fa78c88SVaclav Hapla /*@
241320f4b53cSBarry Smith DMPlexIsDistributed - Find out whether this `DM` is distributed, i.e. more than one rank owns some points.
24145fa78c88SVaclav Hapla
24155fa78c88SVaclav Hapla Collective
24165fa78c88SVaclav Hapla
24175fa78c88SVaclav Hapla Input Parameter:
241820f4b53cSBarry Smith . dm - The `DM` object
24195fa78c88SVaclav Hapla
24205fa78c88SVaclav Hapla Output Parameter:
242120f4b53cSBarry Smith . distributed - Flag whether the `DM` is distributed
24225fa78c88SVaclav Hapla
24235fa78c88SVaclav Hapla Level: intermediate
24245fa78c88SVaclav Hapla
24255fa78c88SVaclav Hapla Notes:
24265fa78c88SVaclav Hapla This currently finds out whether at least two ranks have any DAG points.
242720f4b53cSBarry Smith This involves `MPI_Allreduce()` with one integer.
24285fa78c88SVaclav Hapla The result is currently not stashed so every call to this routine involves this global communication.
24295fa78c88SVaclav Hapla
243060225df5SJacob Faibussowitsch .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetOverlap()`, `DMPlexIsInterpolated()`
24315fa78c88SVaclav Hapla @*/
DMPlexIsDistributed(DM dm,PetscBool * distributed)2432d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsDistributed(DM dm, PetscBool *distributed)
2433d71ae5a4SJacob Faibussowitsch {
24345fa78c88SVaclav Hapla PetscInt pStart, pEnd, count;
24355fa78c88SVaclav Hapla MPI_Comm comm;
243635d70e31SStefano Zampini PetscMPIInt size;
24375fa78c88SVaclav Hapla
24385fa78c88SVaclav Hapla PetscFunctionBegin;
24395fa78c88SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24404f572ea9SToby Isaac PetscAssertPointer(distributed, 2);
24419566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
24429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
24439371c9d4SSatish Balay if (size == 1) {
24449371c9d4SSatish Balay *distributed = PETSC_FALSE;
24453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
24469371c9d4SSatish Balay }
24479566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
244835d70e31SStefano Zampini count = (pEnd - pStart) > 0 ? 1 : 0;
2449462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &count, 1, MPIU_INT, MPI_SUM, comm));
24505fa78c88SVaclav Hapla *distributed = count > 1 ? PETSC_TRUE : PETSC_FALSE;
24513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
24525fa78c88SVaclav Hapla }
24531d1f2f2aSksagiyam
2454cc4c1da9SBarry Smith /*@
24551d1f2f2aSksagiyam DMPlexDistributionSetName - Set the name of the specific parallel distribution
24561d1f2f2aSksagiyam
24571d1f2f2aSksagiyam Input Parameters:
245820f4b53cSBarry Smith + dm - The `DM`
24591d1f2f2aSksagiyam - name - The name of the specific parallel distribution
24601d1f2f2aSksagiyam
24611d1f2f2aSksagiyam Level: developer
24621d1f2f2aSksagiyam
246320f4b53cSBarry Smith Note:
246420f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's
246520f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under
246620f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()`
246720f4b53cSBarry Smith loads the parallel distribution stored in file under this name.
246820f4b53cSBarry Smith
246920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionGetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()`
24701d1f2f2aSksagiyam @*/
DMPlexDistributionSetName(DM dm,const char name[])2471d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionSetName(DM dm, const char name[])
2472d71ae5a4SJacob Faibussowitsch {
24731d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data;
24741d1f2f2aSksagiyam
24751d1f2f2aSksagiyam PetscFunctionBegin;
24761d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX);
24774f572ea9SToby Isaac if (name) PetscAssertPointer(name, 2);
24781d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName));
24791d1f2f2aSksagiyam PetscCall(PetscStrallocpy(name, &mesh->distributionName));
24803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
24811d1f2f2aSksagiyam }
24821d1f2f2aSksagiyam
2483cc4c1da9SBarry Smith /*@
24841d1f2f2aSksagiyam DMPlexDistributionGetName - Retrieve the name of the specific parallel distribution
24851d1f2f2aSksagiyam
24861d1f2f2aSksagiyam Input Parameter:
248720f4b53cSBarry Smith . dm - The `DM`
24881d1f2f2aSksagiyam
24891d1f2f2aSksagiyam Output Parameter:
24901d1f2f2aSksagiyam . name - The name of the specific parallel distribution
24911d1f2f2aSksagiyam
24921d1f2f2aSksagiyam Level: developer
24931d1f2f2aSksagiyam
249420f4b53cSBarry Smith Note:
249520f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's
249620f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under
249720f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()`
249820f4b53cSBarry Smith loads the parallel distribution stored in file under this name.
249920f4b53cSBarry Smith
250020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionSetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()`
25011d1f2f2aSksagiyam @*/
DMPlexDistributionGetName(DM dm,const char * name[])2502d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionGetName(DM dm, const char *name[])
2503d71ae5a4SJacob Faibussowitsch {
25041d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data;
25051d1f2f2aSksagiyam
25061d1f2f2aSksagiyam PetscFunctionBegin;
25071d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX);
25084f572ea9SToby Isaac PetscAssertPointer(name, 2);
25091d1f2f2aSksagiyam *name = mesh->distributionName;
25103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
25111d1f2f2aSksagiyam }
2512