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 @*/ 22d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAdjacencyUser(DM dm, PetscErrorCode (*user)(DM, PetscInt, PetscInt *, PetscInt[], void *), void *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 @*/ 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 @*/ 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 @*/ 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 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 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 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 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 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 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 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 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 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 @*/ 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 @*/ 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 */ 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 @*/ 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 @*/ 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 @*/ 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) */ 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 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 @*/ 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 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 @*/ 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 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 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 @*/ 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 @*/ 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 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 @*/ 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 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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