1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/ 3*3b9d9b65SStefano 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 18016bce5ddSJames Wright // Returns the maximum number of adjancent 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 100320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeFieldIS()`, `DMPlexDistributeData()` 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 104920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexDistributeData()` 105070034214SMatthew G. Knepley @*/ 1051d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeFieldIS(DM dm, PetscSF pointSF, PetscSection originalSection, IS originalIS, PetscSection newSection, IS *newIS) 1052d71ae5a4SJacob Faibussowitsch { 105370034214SMatthew G. Knepley PetscSF fieldSF; 105470034214SMatthew G. Knepley PetscInt *newValues, *remoteOffsets, fieldSize; 105570034214SMatthew G. Knepley const PetscInt *originalValues; 105670034214SMatthew G. Knepley 105770034214SMatthew G. Knepley PetscFunctionBegin; 10589566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeField, dm, 0, 0, 0)); 10599566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 106070034214SMatthew G. Knepley 10619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 10629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(fieldSize, &newValues)); 106370034214SMatthew G. Knepley 10649566063dSJacob Faibussowitsch PetscCall(ISGetIndices(originalIS, &originalValues)); 10659566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 10669566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 10679566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, MPIU_INT, (PetscInt *)originalValues, newValues, MPI_REPLACE)); 10689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, MPIU_INT, (PetscInt *)originalValues, newValues, MPI_REPLACE)); 10699566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 10709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(originalIS, &originalValues)); 10719566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pointSF), fieldSize, newValues, PETSC_OWN_POINTER, newIS)); 10729566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeField, dm, 0, 0, 0)); 10733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 107470034214SMatthew G. Knepley } 107570034214SMatthew G. Knepley 107670034214SMatthew G. Knepley /*@ 107720f4b53cSBarry Smith DMPlexDistributeData - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 107870034214SMatthew G. Knepley 107920f4b53cSBarry Smith Collective 108070034214SMatthew G. Knepley 108170034214SMatthew G. Knepley Input Parameters: 108220f4b53cSBarry Smith + dm - The `DMPLEX` object 108320f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 108420f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 108570034214SMatthew G. Knepley . datatype - The type of data 108670034214SMatthew G. Knepley - originalData - The existing data 108770034214SMatthew G. Knepley 108870034214SMatthew G. Knepley Output Parameters: 108920f4b53cSBarry Smith + newSection - The `PetscSection` describing the new data layout 109070034214SMatthew G. Knepley - newData - The new data 109170034214SMatthew G. Knepley 109270034214SMatthew G. Knepley Level: developer 109370034214SMatthew G. Knepley 109420f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeField()` 109570034214SMatthew G. Knepley @*/ 1096d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeData(DM dm, PetscSF pointSF, PetscSection originalSection, MPI_Datatype datatype, void *originalData, PetscSection newSection, void **newData) 1097d71ae5a4SJacob Faibussowitsch { 109870034214SMatthew G. Knepley PetscSF fieldSF; 109970034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize; 110070034214SMatthew G. Knepley PetscMPIInt dataSize; 110170034214SMatthew G. Knepley 110270034214SMatthew G. Knepley PetscFunctionBegin; 11039566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeData, dm, 0, 0, 0)); 11049566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 110570034214SMatthew G. Knepley 11069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 11079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_size(datatype, &dataSize)); 11089566063dSJacob Faibussowitsch PetscCall(PetscMalloc(fieldSize * dataSize, newData)); 110970034214SMatthew G. Knepley 11109566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 11119566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 11129566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, datatype, originalData, *newData, MPI_REPLACE)); 11139566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, datatype, originalData, *newData, MPI_REPLACE)); 11149566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 11159566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeData, dm, 0, 0, 0)); 11163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 111770034214SMatthew G. Knepley } 111870034214SMatthew G. Knepley 1119d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeCones(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel) 1120d71ae5a4SJacob Faibussowitsch { 112157508eceSPierre Jolivet DM_Plex *pmesh = (DM_Plex *)dmParallel->data; 1122cc71bff1SMichael Lange MPI_Comm comm; 1123cc71bff1SMichael Lange PetscSF coneSF; 1124cc71bff1SMichael Lange PetscSection originalConeSection, newConeSection; 1125ac04eaf7SToby Isaac PetscInt *remoteOffsets, *cones, *globCones, *newCones, newConesSize; 1126cc71bff1SMichael Lange PetscBool flg; 1127cc71bff1SMichael Lange 1128cc71bff1SMichael Lange PetscFunctionBegin; 1129cc71bff1SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 11300c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5); 11319566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeCones, dm, 0, 0, 0)); 1132cc71bff1SMichael Lange /* Distribute cone section */ 11339566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 11349566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &originalConeSection)); 11359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dmParallel, &newConeSection)); 11369566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(migrationSF, originalConeSection, &remoteOffsets, newConeSection)); 11379566063dSJacob Faibussowitsch PetscCall(DMSetUp(dmParallel)); 1138cc71bff1SMichael Lange /* Communicate and renumber cones */ 11399566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(migrationSF, originalConeSection, remoteOffsets, newConeSection, &coneSF)); 11409566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 11419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 1142ac04eaf7SToby Isaac if (original) { 1143ac04eaf7SToby Isaac PetscInt numCones; 1144ac04eaf7SToby Isaac 11459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(originalConeSection, &numCones)); 11469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCones, &globCones)); 11479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(original, numCones, cones, globCones)); 1148367003a6SStefano Zampini } else { 1149ac04eaf7SToby Isaac globCones = cones; 1150ac04eaf7SToby Isaac } 11519566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dmParallel, &newCones)); 11529566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coneSF, MPIU_INT, globCones, newCones, MPI_REPLACE)); 11539566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coneSF, MPIU_INT, globCones, newCones, MPI_REPLACE)); 11541baa6e33SBarry Smith if (original) PetscCall(PetscFree(globCones)); 11559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newConeSection, &newConesSize)); 11569566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones)); 115776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 11583533c52bSMatthew G. Knepley PetscInt p; 11593533c52bSMatthew G. Knepley PetscBool valid = PETSC_TRUE; 11603533c52bSMatthew G. Knepley for (p = 0; p < newConesSize; ++p) { 11619371c9d4SSatish Balay if (newCones[p] < 0) { 11629371c9d4SSatish Balay valid = PETSC_FALSE; 11639371c9d4SSatish Balay PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Point %" PetscInt_FMT " not in overlap SF\n", PetscGlobalRank, p)); 11649371c9d4SSatish Balay } 11653533c52bSMatthew G. Knepley } 116628b400f6SJacob Faibussowitsch PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map"); 11673533c52bSMatthew G. Knepley } 11689566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-cones_view", &flg)); 1169cc71bff1SMichael Lange if (flg) { 11709566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Serial Cone Section:\n")); 11719566063dSJacob Faibussowitsch PetscCall(PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_(comm))); 11729566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Parallel Cone Section:\n")); 11739566063dSJacob Faibussowitsch PetscCall(PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_(comm))); 11749566063dSJacob Faibussowitsch PetscCall(PetscSFView(coneSF, NULL)); 1175cc71bff1SMichael Lange } 11769566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dm, &cones)); 11779566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dmParallel, &newCones)); 11789566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones, MPI_REPLACE)); 11799566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones, MPI_REPLACE)); 11809566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coneSF)); 11819566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeCones, dm, 0, 0, 0)); 1182eaf898f9SPatrick Sanan /* Create supports and stratify DMPlex */ 1183cc71bff1SMichael Lange { 1184cc71bff1SMichael Lange PetscInt pStart, pEnd; 1185cc71bff1SMichael Lange 11869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd)); 11879566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(pmesh->supportSection, pStart, pEnd)); 1188cc71bff1SMichael Lange } 11899566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dmParallel)); 11909566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dmParallel)); 11911cf84007SMatthew G. Knepley { 11921cf84007SMatthew G. Knepley PetscBool useCone, useClosure, useAnchors; 11931cf84007SMatthew G. Knepley 11949566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 11959566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dmParallel, useCone, useClosure)); 11969566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors)); 11979566063dSJacob Faibussowitsch PetscCall(DMPlexSetAdjacencyUseAnchors(dmParallel, useAnchors)); 11981cf84007SMatthew G. Knepley } 11993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1200cc71bff1SMichael Lange } 1201cc71bff1SMichael Lange 1202d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeCoordinates(DM dm, PetscSF migrationSF, DM dmParallel) 1203d71ae5a4SJacob Faibussowitsch { 12040df0e737SMichael Lange MPI_Comm comm; 12059318fe57SMatthew G. Knepley DM cdm, cdmParallel; 12060df0e737SMichael Lange PetscSection originalCoordSection, newCoordSection; 12070df0e737SMichael Lange Vec originalCoordinates, newCoordinates; 12080df0e737SMichael Lange PetscInt bs; 12090df0e737SMichael Lange const char *name; 12104fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 12110df0e737SMichael Lange 12120df0e737SMichael Lange PetscFunctionBegin; 12130df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 12140c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3); 12150df0e737SMichael Lange 12169566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12176858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 12186858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dmParallel, &cdmParallel)); 12196858538eSMatthew G. Knepley PetscCall(DMCopyDisc(cdm, cdmParallel)); 12209566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &originalCoordSection)); 12219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmParallel, &newCoordSection)); 12229566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &originalCoordinates)); 12230df0e737SMichael Lange if (originalCoordinates) { 12249566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates)); 12259566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalCoordinates, &name)); 12269566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)newCoordinates, name)); 12270df0e737SMichael Lange 12289566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates)); 12299566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmParallel, newCoordinates)); 12309566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(originalCoordinates, &bs)); 12319566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(newCoordinates, bs)); 12329566063dSJacob Faibussowitsch PetscCall(VecDestroy(&newCoordinates)); 12330df0e737SMichael Lange } 12346858538eSMatthew G. Knepley 12356858538eSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12364fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L)); 12374fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmParallel, maxCell, Lstart, L)); 12386858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdm)); 12396858538eSMatthew G. Knepley if (cdm) { 12406858538eSMatthew G. Knepley PetscCall(DMClone(dmParallel, &cdmParallel)); 12416858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmParallel, cdmParallel)); 12429566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(cdm, cdmParallel)); 12436858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmParallel)); 12446858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &originalCoordSection)); 12456858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &originalCoordinates)); 12466858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(comm, &newCoordSection)); 12476858538eSMatthew G. Knepley if (originalCoordinates) { 12486858538eSMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates)); 12496858538eSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)originalCoordinates, &name)); 12506858538eSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)newCoordinates, name)); 12516858538eSMatthew G. Knepley 12526858538eSMatthew G. Knepley PetscCall(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates)); 12536858538eSMatthew G. Knepley PetscCall(VecGetBlockSize(originalCoordinates, &bs)); 12546858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(newCoordinates, bs)); 12556858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(dmParallel, bs, newCoordSection)); 12566858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmParallel, newCoordinates)); 12576858538eSMatthew G. Knepley PetscCall(VecDestroy(&newCoordinates)); 12586858538eSMatthew G. Knepley } 12596858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&newCoordSection)); 12606858538eSMatthew G. Knepley } 12613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12620df0e737SMichael Lange } 12630df0e737SMichael Lange 1264d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeLabels(DM dm, PetscSF migrationSF, DM dmParallel) 1265d71ae5a4SJacob Faibussowitsch { 1266df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 12670df0e737SMichael Lange MPI_Comm comm; 12687980c9d4SMatthew G. Knepley DMLabel depthLabel; 12690df0e737SMichael Lange PetscMPIInt rank; 12707980c9d4SMatthew G. Knepley PetscInt depth, d, numLabels, numLocalLabels, l; 1271df0420ecSMatthew G. Knepley PetscBool hasLabels = PETSC_FALSE, lsendDepth, sendDepth; 1272df0420ecSMatthew G. Knepley PetscObjectState depthState = -1; 12730df0e737SMichael Lange 12740df0e737SMichael Lange PetscFunctionBegin; 12750df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 12760c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3); 12770c86c063SLisandro Dalcin 12789566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeLabels, dm, 0, 0, 0)); 12799566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 12810df0e737SMichael Lange 1282df0420ecSMatthew G. Knepley /* If the user has changed the depth label, communicate it instead */ 12839566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 12849566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 12859566063dSJacob Faibussowitsch if (depthLabel) PetscCall(PetscObjectStateGet((PetscObject)depthLabel, &depthState)); 1286df0420ecSMatthew G. Knepley lsendDepth = mesh->depthState != depthState ? PETSC_TRUE : PETSC_FALSE; 12875440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lsendDepth, &sendDepth, 1, MPI_C_BOOL, MPI_LOR, comm)); 1288df0420ecSMatthew G. Knepley if (sendDepth) { 12899566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dmParallel, &dmParallel->depthLabel)); 12909566063dSJacob Faibussowitsch PetscCall(DMRemoveLabelBySelf(dmParallel, &dmParallel->depthLabel, PETSC_FALSE)); 1291df0420ecSMatthew G. Knepley } 1292d995df53SMatthew G. Knepley /* Everyone must have either the same number of labels, or none */ 12939566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLocalLabels)); 1294d995df53SMatthew G. Knepley numLabels = numLocalLabels; 12959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm)); 1296627847f0SMatthew G. Knepley if (numLabels == numLocalLabels) hasLabels = PETSC_TRUE; 12975d80c0bfSVaclav Hapla for (l = 0; l < numLabels; ++l) { 1298bdd2d751SMichael Lange DMLabel label = NULL, labelNew = NULL; 129983e10cb3SLisandro Dalcin PetscBool isDepth, lisOutput = PETSC_TRUE, isOutput; 1300d67d17b1SMatthew G. Knepley const char *name = NULL; 13010df0e737SMichael Lange 1302d67d17b1SMatthew G. Knepley if (hasLabels) { 13039566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(dm, l, &label)); 13040df0e737SMichael Lange /* Skip "depth" because it is recreated */ 13059566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)label, &name)); 13069566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 1307bbcf679cSJacob Faibussowitsch } else { 1308bbcf679cSJacob Faibussowitsch isDepth = PETSC_FALSE; 1309d67d17b1SMatthew G. Knepley } 13105440e5dcSBarry Smith PetscCallMPI(MPI_Bcast(&isDepth, 1, MPI_C_BOOL, 0, comm)); 131183e10cb3SLisandro Dalcin if (isDepth && !sendDepth) continue; 13129566063dSJacob Faibussowitsch PetscCall(DMLabelDistribute(label, migrationSF, &labelNew)); 131383e10cb3SLisandro Dalcin if (isDepth) { 13147980c9d4SMatthew G. Knepley /* Put in any missing strata which can occur if users are managing the depth label themselves */ 13157980c9d4SMatthew G. Knepley PetscInt gdepth; 13167980c9d4SMatthew G. Knepley 1317462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&depth, &gdepth, 1, MPIU_INT, MPI_MAX, comm)); 131863a3b9bcSJacob Faibussowitsch PetscCheck(!(depth >= 0) || !(gdepth != depth), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %" PetscInt_FMT " != %" PetscInt_FMT, depth, gdepth); 13197980c9d4SMatthew G. Knepley for (d = 0; d <= gdepth; ++d) { 13207980c9d4SMatthew G. Knepley PetscBool has; 13217980c9d4SMatthew G. Knepley 13229566063dSJacob Faibussowitsch PetscCall(DMLabelHasStratum(labelNew, d, &has)); 13239566063dSJacob Faibussowitsch if (!has) PetscCall(DMLabelAddStratum(labelNew, d)); 13247980c9d4SMatthew G. Knepley } 13257980c9d4SMatthew G. Knepley } 13269566063dSJacob Faibussowitsch PetscCall(DMAddLabel(dmParallel, labelNew)); 132783e10cb3SLisandro Dalcin /* Put the output flag in the new label */ 13289566063dSJacob Faibussowitsch if (hasLabels) PetscCall(DMGetLabelOutput(dm, name, &lisOutput)); 13295440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lisOutput, &isOutput, 1, MPI_C_BOOL, MPI_LAND, comm)); 13309566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)labelNew, &name)); 13319566063dSJacob Faibussowitsch PetscCall(DMSetLabelOutput(dmParallel, name, isOutput)); 13329566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&labelNew)); 13330df0e737SMichael Lange } 1334695799ffSMatthew G. Knepley { 1335695799ffSMatthew G. Knepley DMLabel ctLabel; 1336695799ffSMatthew G. Knepley 1337695799ffSMatthew G. Knepley // Reset label for fast lookup 1338695799ffSMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dmParallel, &ctLabel)); 1339695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 1340695799ffSMatthew G. Knepley } 13419566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeLabels, dm, 0, 0, 0)); 13423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13430df0e737SMichael Lange } 13440df0e737SMichael Lange 1345d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeSetupTree(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel) 1346d71ae5a4SJacob Faibussowitsch { 134715078cd4SMichael Lange DM_Plex *mesh = (DM_Plex *)dm->data; 134857508eceSPierre Jolivet DM_Plex *pmesh = (DM_Plex *)dmParallel->data; 1349a6f36705SMichael Lange MPI_Comm comm; 1350a6f36705SMichael Lange DM refTree; 1351a6f36705SMichael Lange PetscSection origParentSection, newParentSection; 1352a6f36705SMichael Lange PetscInt *origParents, *origChildIDs; 1353a6f36705SMichael Lange PetscBool flg; 1354a6f36705SMichael Lange 1355a6f36705SMichael Lange PetscFunctionBegin; 1356a6f36705SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13570c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5); 13589566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 1359a6f36705SMichael Lange 1360a6f36705SMichael Lange /* Set up tree */ 13619566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 13629566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(dmParallel, refTree)); 13639566063dSJacob Faibussowitsch PetscCall(DMPlexGetTree(dm, &origParentSection, &origParents, &origChildIDs, NULL, NULL)); 1364a6f36705SMichael Lange if (origParentSection) { 1365a6f36705SMichael Lange PetscInt pStart, pEnd; 136608633170SToby Isaac PetscInt *newParents, *newChildIDs, *globParents; 1367a6f36705SMichael Lange PetscInt *remoteOffsetsParents, newParentSize; 1368a6f36705SMichael Lange PetscSF parentSF; 1369a6f36705SMichael Lange 13709566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmParallel, &pStart, &pEnd)); 13719566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmParallel), &newParentSection)); 13729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newParentSection, pStart, pEnd)); 13739566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(migrationSF, origParentSection, &remoteOffsetsParents, newParentSection)); 13749566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(migrationSF, origParentSection, remoteOffsetsParents, newParentSection, &parentSF)); 13759566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsParents)); 13769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newParentSection, &newParentSize)); 13779566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(newParentSize, &newParents, newParentSize, &newChildIDs)); 137808633170SToby Isaac if (original) { 137908633170SToby Isaac PetscInt numParents; 138008633170SToby Isaac 13819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(origParentSection, &numParents)); 13829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numParents, &globParents)); 13839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(original, numParents, origParents, globParents)); 13849371c9d4SSatish Balay } else { 138508633170SToby Isaac globParents = origParents; 138608633170SToby Isaac } 13879566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(parentSF, MPIU_INT, globParents, newParents, MPI_REPLACE)); 13889566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(parentSF, MPIU_INT, globParents, newParents, MPI_REPLACE)); 13891baa6e33SBarry Smith if (original) PetscCall(PetscFree(globParents)); 13909566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(parentSF, MPIU_INT, origChildIDs, newChildIDs, MPI_REPLACE)); 13919566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(parentSF, MPIU_INT, origChildIDs, newChildIDs, MPI_REPLACE)); 13929566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newParentSize, newParents, NULL, newParents)); 139376bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 13944a54e071SToby Isaac PetscInt p; 13954a54e071SToby Isaac PetscBool valid = PETSC_TRUE; 13964a54e071SToby Isaac for (p = 0; p < newParentSize; ++p) { 13979371c9d4SSatish Balay if (newParents[p] < 0) { 13989371c9d4SSatish Balay valid = PETSC_FALSE; 13999371c9d4SSatish Balay PetscCall(PetscPrintf(PETSC_COMM_SELF, "Point %" PetscInt_FMT " not in overlap SF\n", p)); 14009371c9d4SSatish Balay } 14014a54e071SToby Isaac } 140228b400f6SJacob Faibussowitsch PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map"); 14034a54e071SToby Isaac } 14049566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-parents_view", &flg)); 1405a6f36705SMichael Lange if (flg) { 14069566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Serial Parent Section: \n")); 14079566063dSJacob Faibussowitsch PetscCall(PetscSectionView(origParentSection, PETSC_VIEWER_STDOUT_(comm))); 14089566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Parallel Parent Section: \n")); 14099566063dSJacob Faibussowitsch PetscCall(PetscSectionView(newParentSection, PETSC_VIEWER_STDOUT_(comm))); 14109566063dSJacob Faibussowitsch PetscCall(PetscSFView(parentSF, NULL)); 1411a6f36705SMichael Lange } 14129566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(dmParallel, newParentSection, newParents, newChildIDs)); 14139566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newParentSection)); 14149566063dSJacob Faibussowitsch PetscCall(PetscFree2(newParents, newChildIDs)); 14159566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&parentSF)); 1416a6f36705SMichael Lange } 141715078cd4SMichael Lange pmesh->useAnchors = mesh->useAnchors; 14183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1419a6f36705SMichael Lange } 14200df0e737SMichael Lange 142198ba2d7fSLawrence Mitchell /*@ 142220f4b53cSBarry Smith DMPlexSetPartitionBalance - Should distribution of the `DM` attempt to balance the shared point partition? 142398ba2d7fSLawrence Mitchell 142498ba2d7fSLawrence Mitchell Input Parameters: 142520f4b53cSBarry Smith + dm - The `DMPLEX` object 142698ba2d7fSLawrence Mitchell - flg - Balance the partition? 142798ba2d7fSLawrence Mitchell 142898ba2d7fSLawrence Mitchell Level: intermediate 142998ba2d7fSLawrence Mitchell 143020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetPartitionBalance()` 143198ba2d7fSLawrence Mitchell @*/ 1432d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetPartitionBalance(DM dm, PetscBool flg) 1433d71ae5a4SJacob Faibussowitsch { 143498ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 143598ba2d7fSLawrence Mitchell 143698ba2d7fSLawrence Mitchell PetscFunctionBegin; 143798ba2d7fSLawrence Mitchell mesh->partitionBalance = flg; 14383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 143998ba2d7fSLawrence Mitchell } 144098ba2d7fSLawrence Mitchell 144198ba2d7fSLawrence Mitchell /*@ 144220f4b53cSBarry Smith DMPlexGetPartitionBalance - Does distribution of the `DM` attempt to balance the shared point partition? 144398ba2d7fSLawrence Mitchell 144498ba2d7fSLawrence Mitchell Input Parameter: 144520f4b53cSBarry Smith . dm - The `DMPLEX` object 144698ba2d7fSLawrence Mitchell 144798ba2d7fSLawrence Mitchell Output Parameter: 1448a2b725a8SWilliam Gropp . flg - Balance the partition? 144998ba2d7fSLawrence Mitchell 145098ba2d7fSLawrence Mitchell Level: intermediate 145198ba2d7fSLawrence Mitchell 145220f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexSetPartitionBalance()` 145398ba2d7fSLawrence Mitchell @*/ 1454d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPartitionBalance(DM dm, PetscBool *flg) 1455d71ae5a4SJacob Faibussowitsch { 145698ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 145798ba2d7fSLawrence Mitchell 145898ba2d7fSLawrence Mitchell PetscFunctionBegin; 145998ba2d7fSLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14604f572ea9SToby Isaac PetscAssertPointer(flg, 2); 146198ba2d7fSLawrence Mitchell *flg = mesh->partitionBalance; 14623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 146398ba2d7fSLawrence Mitchell } 146498ba2d7fSLawrence Mitchell 1465fc02256fSLawrence Mitchell typedef struct { 1466fc02256fSLawrence Mitchell PetscInt vote, rank, index; 1467fc02256fSLawrence Mitchell } Petsc3Int; 1468fc02256fSLawrence Mitchell 1469fc02256fSLawrence Mitchell /* MaxLoc, but carry a third piece of information around */ 1470d71ae5a4SJacob Faibussowitsch static void MPIAPI MaxLocCarry(void *in_, void *inout_, PetscMPIInt *len_, MPI_Datatype *dtype) 1471d71ae5a4SJacob Faibussowitsch { 1472fc02256fSLawrence Mitchell Petsc3Int *a = (Petsc3Int *)inout_; 1473fc02256fSLawrence Mitchell Petsc3Int *b = (Petsc3Int *)in_; 1474fc02256fSLawrence Mitchell PetscInt i, len = *len_; 1475fc02256fSLawrence Mitchell for (i = 0; i < len; i++) { 1476fc02256fSLawrence Mitchell if (a[i].vote < b[i].vote) { 1477fc02256fSLawrence Mitchell a[i].vote = b[i].vote; 1478fc02256fSLawrence Mitchell a[i].rank = b[i].rank; 1479fc02256fSLawrence Mitchell a[i].index = b[i].index; 1480fc02256fSLawrence Mitchell } else if (a[i].vote <= b[i].vote) { 1481fc02256fSLawrence Mitchell if (a[i].rank >= b[i].rank) { 1482fc02256fSLawrence Mitchell a[i].rank = b[i].rank; 1483fc02256fSLawrence Mitchell a[i].index = b[i].index; 1484fc02256fSLawrence Mitchell } 1485fc02256fSLawrence Mitchell } 1486fc02256fSLawrence Mitchell } 1487fc02256fSLawrence Mitchell } 1488fc02256fSLawrence Mitchell 1489cc4c1da9SBarry Smith /*@ 149020f4b53cSBarry Smith DMPlexCreatePointSF - Build a point `PetscSF` from an `PetscSF` describing a point migration 1491f5bf2dbfSMichael Lange 1492064ec1f3Sprj- Input Parameters: 149320f4b53cSBarry Smith + dm - The source `DMPLEX` object 1494f5bf2dbfSMichael Lange . migrationSF - The star forest that describes the parallel point remapping 1495d8d19677SJose E. Roman - ownership - Flag causing a vote to determine point ownership 1496f5bf2dbfSMichael Lange 1497f5bf2dbfSMichael Lange Output Parameter: 149820f4b53cSBarry Smith . pointSF - The star forest describing the point overlap in the remapped `DM` 14993618482eSVaclav Hapla 1500f5bf2dbfSMichael Lange Level: developer 1501f5bf2dbfSMichael Lange 150220f4b53cSBarry Smith Note: 150320f4b53cSBarry Smith Output `pointSF` is guaranteed to have the array of local indices (leaves) sorted. 150420f4b53cSBarry Smith 150520f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 1506f5bf2dbfSMichael Lange @*/ 1507d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointSF(DM dm, PetscSF migrationSF, PetscBool ownership, PetscSF *pointSF) 1508d71ae5a4SJacob Faibussowitsch { 150923193802SMatthew G. Knepley PetscMPIInt rank, size; 15101627f6ccSMichael Lange PetscInt p, nroots, nleaves, idx, npointLeaves; 1511f5bf2dbfSMichael Lange PetscInt *pointLocal; 1512f5bf2dbfSMichael Lange const PetscInt *leaves; 1513f5bf2dbfSMichael Lange const PetscSFNode *roots; 1514f5bf2dbfSMichael Lange PetscSFNode *rootNodes, *leafNodes, *pointRemote; 151523193802SMatthew G. Knepley Vec shifts; 1516cae3e4f3SLawrence Mitchell const PetscInt numShifts = 13759; 151723193802SMatthew G. Knepley const PetscScalar *shift = NULL; 151823193802SMatthew G. Knepley const PetscBool shiftDebug = PETSC_FALSE; 151998ba2d7fSLawrence Mitchell PetscBool balance; 1520f5bf2dbfSMichael Lange 1521f5bf2dbfSMichael Lange PetscFunctionBegin; 1522f5bf2dbfSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 15239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 15259566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreatePointSF, dm, 0, 0, 0)); 1526907a3e9cSStefano Zampini PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), pointSF)); 1527907a3e9cSStefano Zampini PetscCall(PetscSFSetFromOptions(*pointSF)); 1528907a3e9cSStefano Zampini if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 1529f5bf2dbfSMichael Lange 15309566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitionBalance(dm, &balance)); 15319566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(migrationSF, &nroots, &nleaves, &leaves, &roots)); 15329566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &rootNodes, nleaves, &leafNodes)); 1533f5bf2dbfSMichael Lange if (ownership) { 1534fc02256fSLawrence Mitchell MPI_Op op; 1535fc02256fSLawrence Mitchell MPI_Datatype datatype; 1536fc02256fSLawrence Mitchell Petsc3Int *rootVote = NULL, *leafVote = NULL; 15376497c311SBarry Smith 153823193802SMatthew 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. */ 153998ba2d7fSLawrence Mitchell if (balance) { 154023193802SMatthew G. Knepley PetscRandom r; 154123193802SMatthew G. Knepley 15429566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_SELF, &r)); 15439566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(r, 0, 2467 * size)); 15449566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &shifts)); 15459566063dSJacob Faibussowitsch PetscCall(VecSetSizes(shifts, numShifts, numShifts)); 15469566063dSJacob Faibussowitsch PetscCall(VecSetType(shifts, VECSTANDARD)); 15479566063dSJacob Faibussowitsch PetscCall(VecSetRandom(shifts, r)); 15489566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&r)); 15499566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(shifts, &shift)); 155023193802SMatthew G. Knepley } 155123193802SMatthew G. Knepley 15529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nroots, &rootVote)); 15539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &leafVote)); 155423193802SMatthew G. Knepley /* Point ownership vote: Process with highest rank owns shared points */ 1555f5bf2dbfSMichael Lange for (p = 0; p < nleaves; ++p) { 155623193802SMatthew G. Knepley if (shiftDebug) { 15579371c9d4SSatish 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, 15589371c9d4SSatish Balay (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]), (rank + (shift ? (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]) : 0)) % size)); 155923193802SMatthew G. Knepley } 1560f5bf2dbfSMichael Lange /* Either put in a bid or we know we own it */ 1561fc02256fSLawrence Mitchell leafVote[p].vote = (rank + (shift ? (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]) : 0)) % size; 1562fc02256fSLawrence Mitchell leafVote[p].rank = rank; 1563fc02256fSLawrence Mitchell leafVote[p].index = p; 1564f5bf2dbfSMichael Lange } 1565f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) { 15661627f6ccSMichael Lange /* Root must not participate in the reduction, flag so that MAXLOC does not use */ 1567fc02256fSLawrence Mitchell rootVote[p].vote = -3; 1568fc02256fSLawrence Mitchell rootVote[p].rank = -3; 1569fc02256fSLawrence Mitchell rootVote[p].index = -3; 1570f5bf2dbfSMichael Lange } 15719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(3, MPIU_INT, &datatype)); 15729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&datatype)); 15739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(&MaxLocCarry, 1, &op)); 15749566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(migrationSF, datatype, leafVote, rootVote, op)); 15759566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(migrationSF, datatype, leafVote, rootVote, op)); 15769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&op)); 15779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&datatype)); 1578c091126eSLawrence Mitchell for (p = 0; p < nroots; p++) { 1579835f2295SStefano Zampini rootNodes[p].rank = rootVote[p].rank; 1580fc02256fSLawrence Mitchell rootNodes[p].index = rootVote[p].index; 1581c091126eSLawrence Mitchell } 15829566063dSJacob Faibussowitsch PetscCall(PetscFree(leafVote)); 15839566063dSJacob Faibussowitsch PetscCall(PetscFree(rootVote)); 1584f5bf2dbfSMichael Lange } else { 1585f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) { 1586f5bf2dbfSMichael Lange rootNodes[p].index = -1; 1587f5bf2dbfSMichael Lange rootNodes[p].rank = rank; 1588fc02256fSLawrence Mitchell } 1589f5bf2dbfSMichael Lange for (p = 0; p < nleaves; p++) { 1590f5bf2dbfSMichael Lange /* Write new local id into old location */ 1591ad540459SPierre Jolivet if (roots[p].rank == rank) rootNodes[roots[p].index].index = leaves ? leaves[p] : p; 1592f5bf2dbfSMichael Lange } 1593f5bf2dbfSMichael Lange } 15946497c311SBarry Smith PetscCall(PetscSFBcastBegin(migrationSF, MPIU_SF_NODE, rootNodes, leafNodes, MPI_REPLACE)); 15956497c311SBarry Smith PetscCall(PetscSFBcastEnd(migrationSF, MPIU_SF_NODE, rootNodes, leafNodes, MPI_REPLACE)); 1596f5bf2dbfSMichael Lange 159723193802SMatthew G. Knepley for (npointLeaves = 0, p = 0; p < nleaves; p++) { 1598b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) npointLeaves++; 159923193802SMatthew G. Knepley } 16009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npointLeaves, &pointLocal)); 16019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npointLeaves, &pointRemote)); 1602f5bf2dbfSMichael Lange for (idx = 0, p = 0; p < nleaves; p++) { 1603b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) { 16043618482eSVaclav Hapla /* Note that pointLocal is automatically sorted as it is sublist of 0, ..., nleaves-1 */ 1605f5bf2dbfSMichael Lange pointLocal[idx] = p; 1606f5bf2dbfSMichael Lange pointRemote[idx] = leafNodes[p]; 1607f5bf2dbfSMichael Lange idx++; 1608f5bf2dbfSMichael Lange } 1609f5bf2dbfSMichael Lange } 161023193802SMatthew G. Knepley if (shift) { 16119566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(shifts, &shift)); 16129566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shifts)); 161323193802SMatthew G. Knepley } 16149566063dSJacob Faibussowitsch if (shiftDebug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), PETSC_STDOUT)); 16159566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*pointSF, nleaves, npointLeaves, pointLocal, PETSC_OWN_POINTER, pointRemote, PETSC_OWN_POINTER)); 16169566063dSJacob Faibussowitsch PetscCall(PetscFree2(rootNodes, leafNodes)); 16179566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreatePointSF, dm, 0, 0, 0)); 1618d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, *pointSF, PETSC_FALSE)); 16193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1620f5bf2dbfSMichael Lange } 1621f5bf2dbfSMichael Lange 1622cc4c1da9SBarry Smith /*@ 162320f4b53cSBarry Smith DMPlexMigrate - Migrates internal `DM` data over the supplied star forest 162415078cd4SMichael Lange 162520f4b53cSBarry Smith Collective 162683655b49SVáclav Hapla 1627064ec1f3Sprj- Input Parameters: 162820f4b53cSBarry Smith + dm - The source `DMPLEX` object 1629d8d19677SJose E. Roman - sf - The star forest communication context describing the migration pattern 163015078cd4SMichael Lange 163115078cd4SMichael Lange Output Parameter: 163220f4b53cSBarry Smith . targetDM - The target `DMPLEX` object 163315078cd4SMichael Lange 1634b9f40539SMichael Lange Level: intermediate 163515078cd4SMichael Lange 163620f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 163715078cd4SMichael Lange @*/ 1638d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMigrate(DM dm, PetscSF sf, DM targetDM) 1639d71ae5a4SJacob Faibussowitsch { 1640b9f40539SMichael Lange MPI_Comm comm; 1641cc1750acSStefano Zampini PetscInt dim, cdim, nroots; 1642b9f40539SMichael Lange PetscSF sfPoint; 164315078cd4SMichael Lange ISLocalToGlobalMapping ltogMigration; 1644ac04eaf7SToby Isaac ISLocalToGlobalMapping ltogOriginal = NULL; 164515078cd4SMichael Lange 164615078cd4SMichael Lange PetscFunctionBegin; 164715078cd4SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 16489566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Migrate, dm, 0, 0, 0)); 16499566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 16509566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 16519566063dSJacob Faibussowitsch PetscCall(DMSetDimension(targetDM, dim)); 16529566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 16539566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(targetDM, cdim)); 165415078cd4SMichael Lange 1655bfb0467fSMichael Lange /* Check for a one-to-all distribution pattern */ 16569566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 16579566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 1658bfb0467fSMichael Lange if (nroots >= 0) { 1659b9f40539SMichael Lange IS isOriginal; 1660ac04eaf7SToby Isaac PetscInt n, size, nleaves; 1661ac04eaf7SToby Isaac PetscInt *numbering_orig, *numbering_new; 1662367003a6SStefano Zampini 1663b9f40539SMichael Lange /* Get the original point numbering */ 16649566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &isOriginal)); 16659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(isOriginal, <ogOriginal)); 16669566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(ltogOriginal, &size)); 16679566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltogOriginal, (const PetscInt **)&numbering_orig)); 1668b9f40539SMichael Lange /* Convert to positive global numbers */ 16699371c9d4SSatish Balay for (n = 0; n < size; n++) { 16709371c9d4SSatish Balay if (numbering_orig[n] < 0) numbering_orig[n] = -(numbering_orig[n] + 1); 16719371c9d4SSatish Balay } 1672b9f40539SMichael Lange /* Derive the new local-to-global mapping from the old one */ 16739566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, NULL, NULL)); 16749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &numbering_new)); 16759566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, numbering_orig, numbering_new, MPI_REPLACE)); 16769566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, numbering_orig, numbering_new, MPI_REPLACE)); 16779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, nleaves, numbering_new, PETSC_OWN_POINTER, <ogMigration)); 16789566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogOriginal, (const PetscInt **)&numbering_orig)); 16799566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isOriginal)); 168015078cd4SMichael Lange } else { 1681bfb0467fSMichael Lange /* One-to-all distribution pattern: We can derive LToG from SF */ 16829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateSF(sf, 0, <ogMigration)); 168315078cd4SMichael Lange } 1684a5a902f7SVaclav Hapla PetscCall(PetscObjectSetName((PetscObject)ltogMigration, "Point renumbering for DM migration")); 1685a5a902f7SVaclav Hapla PetscCall(ISLocalToGlobalMappingViewFromOptions(ltogMigration, (PetscObject)dm, "-partition_view")); 168615078cd4SMichael Lange /* Migrate DM data to target DM */ 16879566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeCones(dm, sf, ltogOriginal, ltogMigration, targetDM)); 16889566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeLabels(dm, sf, targetDM)); 16899566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeCoordinates(dm, sf, targetDM)); 16909566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetupTree(dm, sf, ltogOriginal, ltogMigration, targetDM)); 16919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<ogOriginal)); 16929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<ogMigration)); 16939566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Migrate, dm, 0, 0, 0)); 16943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 169515078cd4SMichael Lange } 169615078cd4SMichael Lange 169700a1aa47SMatthew G. Knepley /*@ 169800a1aa47SMatthew G. Knepley DMPlexRemapMigrationSF - Rewrite the distribution SF to account for overlap 169900a1aa47SMatthew G. Knepley 170000a1aa47SMatthew G. Knepley Collective 170100a1aa47SMatthew G. Knepley 170200a1aa47SMatthew G. Knepley Input Parameters: 170300a1aa47SMatthew G. Knepley + sfOverlap - The `PetscSF` object just for the overlap 170400a1aa47SMatthew G. Knepley - sfMigration - The original distribution `PetscSF` object 170500a1aa47SMatthew G. Knepley 170600a1aa47SMatthew G. Knepley Output Parameters: 170700a1aa47SMatthew G. Knepley . sfMigrationNew - A rewritten `PetscSF` object that incorporates the overlap 170800a1aa47SMatthew G. Knepley 170900a1aa47SMatthew G. Knepley Level: developer 171000a1aa47SMatthew G. Knepley 171100a1aa47SMatthew G. Knepley .seealso: `DMPLEX`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()`, `DMPlexGetOverlap()` 171200a1aa47SMatthew G. Knepley @*/ 171300a1aa47SMatthew G. Knepley PetscErrorCode DMPlexRemapMigrationSF(PetscSF sfOverlap, PetscSF sfMigration, PetscSF *sfMigrationNew) 171400a1aa47SMatthew G. Knepley { 1715835f2295SStefano Zampini PetscSFNode *newRemote, *permRemote = NULL; 171600a1aa47SMatthew G. Knepley const PetscInt *oldLeaves; 171700a1aa47SMatthew G. Knepley const PetscSFNode *oldRemote; 171800a1aa47SMatthew G. Knepley PetscInt nroots, nleaves, noldleaves; 171900a1aa47SMatthew G. Knepley 172000a1aa47SMatthew G. Knepley PetscFunctionBegin; 172100a1aa47SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfMigration, &nroots, &noldleaves, &oldLeaves, &oldRemote)); 172200a1aa47SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfOverlap, NULL, &nleaves, NULL, NULL)); 172300a1aa47SMatthew G. Knepley PetscCall(PetscMalloc1(nleaves, &newRemote)); 172400a1aa47SMatthew G. Knepley /* oldRemote: original root point mapping to original leaf point 172500a1aa47SMatthew G. Knepley newRemote: original leaf point mapping to overlapped leaf point */ 172600a1aa47SMatthew G. Knepley if (oldLeaves) { 172700a1aa47SMatthew G. Knepley /* After stratification, the migration remotes may not be in root (canonical) order, so we reorder using the leaf numbering */ 172800a1aa47SMatthew G. Knepley PetscCall(PetscMalloc1(noldleaves, &permRemote)); 172900a1aa47SMatthew G. Knepley for (PetscInt l = 0; l < noldleaves; ++l) permRemote[oldLeaves[l]] = oldRemote[l]; 173000a1aa47SMatthew G. Knepley oldRemote = permRemote; 173100a1aa47SMatthew G. Knepley } 17326497c311SBarry Smith PetscCall(PetscSFBcastBegin(sfOverlap, MPIU_SF_NODE, oldRemote, newRemote, MPI_REPLACE)); 17336497c311SBarry Smith PetscCall(PetscSFBcastEnd(sfOverlap, MPIU_SF_NODE, oldRemote, newRemote, MPI_REPLACE)); 1734835f2295SStefano Zampini PetscCall(PetscFree(permRemote)); 173500a1aa47SMatthew G. Knepley PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)sfOverlap), sfMigrationNew)); 173600a1aa47SMatthew G. Knepley PetscCall(PetscSFSetGraph(*sfMigrationNew, nroots, nleaves, NULL, PETSC_OWN_POINTER, newRemote, PETSC_OWN_POINTER)); 173700a1aa47SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 173800a1aa47SMatthew G. Knepley } 173900a1aa47SMatthew G. Knepley 1740*3b9d9b65SStefano Zampini /* For DG-like methods, the code below is equivalent (but faster) than calling 1741*3b9d9b65SStefano Zampini DMPlexCreateClosureIndex(dm,section) */ 1742*3b9d9b65SStefano Zampini static PetscErrorCode DMPlexCreateClosureIndex_CELL(DM dm, PetscSection section) 1743*3b9d9b65SStefano Zampini { 1744*3b9d9b65SStefano Zampini PetscSection clSection; 1745*3b9d9b65SStefano Zampini IS clPoints; 1746*3b9d9b65SStefano Zampini PetscInt pStart, pEnd, point; 1747*3b9d9b65SStefano Zampini PetscInt *closure, pos = 0; 1748*3b9d9b65SStefano Zampini 1749*3b9d9b65SStefano Zampini PetscFunctionBegin; 1750*3b9d9b65SStefano Zampini if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 1751*3b9d9b65SStefano Zampini PetscCall(DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd)); 1752*3b9d9b65SStefano Zampini PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &clSection)); 1753*3b9d9b65SStefano Zampini PetscCall(PetscSectionSetChart(clSection, pStart, pEnd)); 1754*3b9d9b65SStefano Zampini PetscCall(PetscMalloc1((2 * (pEnd - pStart)), &closure)); 1755*3b9d9b65SStefano Zampini for (point = pStart; point < pEnd; point++) { 1756*3b9d9b65SStefano Zampini PetscCall(PetscSectionSetDof(clSection, point, 2)); 1757*3b9d9b65SStefano Zampini closure[pos++] = point; /* point */ 1758*3b9d9b65SStefano Zampini closure[pos++] = 0; /* orientation */ 1759*3b9d9b65SStefano Zampini } 1760*3b9d9b65SStefano Zampini PetscCall(PetscSectionSetUp(clSection)); 1761*3b9d9b65SStefano Zampini PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 2 * (pEnd - pStart), closure, PETSC_OWN_POINTER, &clPoints)); 1762*3b9d9b65SStefano Zampini PetscCall(PetscSectionSetClosureIndex(section, (PetscObject)dm, clSection, clPoints)); 1763*3b9d9b65SStefano Zampini PetscCall(PetscSectionDestroy(&clSection)); 1764*3b9d9b65SStefano Zampini PetscCall(ISDestroy(&clPoints)); 1765*3b9d9b65SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1766*3b9d9b65SStefano Zampini } 1767*3b9d9b65SStefano Zampini 1768*3b9d9b65SStefano Zampini static PetscErrorCode DMPlexDistribute_Multistage(DM dm, PetscInt overlap, PetscSF *sf, DM *dmParallel) 1769*3b9d9b65SStefano Zampini { 1770*3b9d9b65SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)dm); 1771*3b9d9b65SStefano Zampini PetscPartitioner part; 1772*3b9d9b65SStefano Zampini PetscBool balance, printHeader; 1773*3b9d9b65SStefano Zampini PetscInt nl = 0; 1774*3b9d9b65SStefano Zampini 1775*3b9d9b65SStefano Zampini PetscFunctionBegin; 1776*3b9d9b65SStefano Zampini if (sf) *sf = NULL; 1777*3b9d9b65SStefano Zampini *dmParallel = NULL; 1778*3b9d9b65SStefano Zampini 1779*3b9d9b65SStefano Zampini PetscCall(DMPlexGetPartitioner(dm, &part)); 1780*3b9d9b65SStefano Zampini printHeader = part->printHeader; 1781*3b9d9b65SStefano Zampini PetscCall(DMPlexGetPartitionBalance(dm, &balance)); 1782*3b9d9b65SStefano Zampini PetscCall(PetscPartitionerSetUp(part)); 1783*3b9d9b65SStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_DistributeMultistage, dm, 0, 0, 0)); 1784*3b9d9b65SStefano Zampini PetscCall(PetscPartitionerMultistageGetStages_Multistage(part, &nl, NULL)); 1785*3b9d9b65SStefano Zampini for (PetscInt l = 0; l < nl; l++) { 1786*3b9d9b65SStefano Zampini PetscInt ovl = (l < nl - 1) ? 0 : overlap; 1787*3b9d9b65SStefano Zampini PetscSF sfDist; 1788*3b9d9b65SStefano Zampini DM dmDist; 1789*3b9d9b65SStefano Zampini 1790*3b9d9b65SStefano Zampini PetscCall(DMPlexSetPartitionBalance(dm, balance)); 1791*3b9d9b65SStefano Zampini PetscCall(DMViewFromOptions(dm, (PetscObject)part, "-petscpartitioner_multistage_dm_view")); 1792*3b9d9b65SStefano Zampini PetscCall(PetscPartitionerMultistageSetStage_Multistage(part, l, (PetscObject)dm)); 1793*3b9d9b65SStefano Zampini PetscCall(DMPlexSetPartitioner(dm, part)); 1794*3b9d9b65SStefano Zampini PetscCall(DMPlexDistribute(dm, ovl, &sfDist, &dmDist)); 1795*3b9d9b65SStefano Zampini PetscCheck(dmDist, comm, PETSC_ERR_PLIB, "No distributed DM generated (stage %" PetscInt_FMT ")", l); 1796*3b9d9b65SStefano Zampini PetscCheck(sfDist, comm, PETSC_ERR_PLIB, "No SF generated (stage %" PetscInt_FMT ")", l); 1797*3b9d9b65SStefano Zampini part->printHeader = PETSC_FALSE; 1798*3b9d9b65SStefano Zampini 1799*3b9d9b65SStefano Zampini /* Propagate cell weights to the next level (if any, and if not the final dm) */ 1800*3b9d9b65SStefano Zampini if (part->usevwgt && dm->localSection && l != nl - 1) { 1801*3b9d9b65SStefano Zampini PetscSection oldSection, newSection; 1802*3b9d9b65SStefano Zampini 1803*3b9d9b65SStefano Zampini PetscCall(DMGetLocalSection(dm, &oldSection)); 1804*3b9d9b65SStefano Zampini PetscCall(DMGetLocalSection(dmDist, &newSection)); 1805*3b9d9b65SStefano Zampini PetscCall(PetscSFDistributeSection(sfDist, oldSection, NULL, newSection)); 1806*3b9d9b65SStefano Zampini PetscCall(DMPlexCreateClosureIndex_CELL(dmDist, newSection)); 1807*3b9d9b65SStefano Zampini } 1808*3b9d9b65SStefano Zampini if (!sf) PetscCall(PetscSFDestroy(&sfDist)); 1809*3b9d9b65SStefano Zampini if (l > 0) PetscCall(DMDestroy(&dm)); 1810*3b9d9b65SStefano Zampini 1811*3b9d9b65SStefano Zampini if (sf && *sf) { 1812*3b9d9b65SStefano Zampini PetscSF sfA = *sf, sfB = sfDist; 1813*3b9d9b65SStefano Zampini PetscCall(PetscSFCompose(sfA, sfB, &sfDist)); 1814*3b9d9b65SStefano Zampini PetscCall(PetscSFDestroy(&sfA)); 1815*3b9d9b65SStefano Zampini PetscCall(PetscSFDestroy(&sfB)); 1816*3b9d9b65SStefano Zampini } 1817*3b9d9b65SStefano Zampini 1818*3b9d9b65SStefano Zampini if (sf) *sf = sfDist; 1819*3b9d9b65SStefano Zampini dm = *dmParallel = dmDist; 1820*3b9d9b65SStefano Zampini } 1821*3b9d9b65SStefano Zampini PetscCall(PetscPartitionerMultistageSetStage_Multistage(part, 0, NULL)); /* reset */ 1822*3b9d9b65SStefano Zampini PetscCall(PetscLogEventEnd(DMPLEX_DistributeMultistage, dm, 0, 0, 0)); 1823*3b9d9b65SStefano Zampini part->printHeader = printHeader; 1824*3b9d9b65SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1825*3b9d9b65SStefano Zampini } 1826*3b9d9b65SStefano Zampini 18275d83a8b1SBarry Smith /*@ 182870034214SMatthew G. Knepley DMPlexDistribute - Distributes the mesh and any associated sections. 182970034214SMatthew G. Knepley 183020f4b53cSBarry Smith Collective 183170034214SMatthew G. Knepley 1832064ec1f3Sprj- Input Parameters: 183320f4b53cSBarry Smith + dm - The original `DMPLEX` object 183470034214SMatthew G. Knepley - overlap - The overlap of partitions, 0 is the default 183570034214SMatthew G. Knepley 1836064ec1f3Sprj- Output Parameters: 183720f4b53cSBarry Smith + sf - The `PetscSF` used for point distribution, or `NULL` if not needed 183820f4b53cSBarry Smith - dmParallel - The distributed `DMPLEX` object 183970034214SMatthew G. Knepley 184070034214SMatthew G. Knepley Level: intermediate 184170034214SMatthew G. Knepley 184220f4b53cSBarry Smith Note: 184320f4b53cSBarry Smith If the mesh was not distributed, the output `dmParallel` will be `NULL`. 184420f4b53cSBarry Smith 184520f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function 184620f4b53cSBarry Smith representation on the mesh. 184720f4b53cSBarry Smith 184820f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexGetOverlap()` 184970034214SMatthew G. Knepley @*/ 1850ce78bad3SBarry Smith PetscErrorCode DMPlexDistribute(DM dm, PetscInt overlap, PeOp PetscSF *sf, DM *dmParallel) 1851d71ae5a4SJacob Faibussowitsch { 185270034214SMatthew G. Knepley MPI_Comm comm; 185315078cd4SMichael Lange PetscPartitioner partitioner; 1854f8987ae8SMichael Lange IS cellPart; 1855f8987ae8SMichael Lange PetscSection cellPartSection; 1856cf86098cSMatthew G. Knepley DM dmCoord; 1857f8987ae8SMichael Lange DMLabel lblPartition, lblMigration; 1858874ddda9SLisandro Dalcin PetscSF sfMigration, sfStratified, sfPoint; 1859*3b9d9b65SStefano Zampini PetscBool flg, balance, isms; 1860874ddda9SLisandro Dalcin PetscMPIInt rank, size; 186170034214SMatthew G. Knepley 186270034214SMatthew G. Knepley PetscFunctionBegin; 186370034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1864d5c515a1SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 2); 18654f572ea9SToby Isaac if (sf) PetscAssertPointer(sf, 3); 18664f572ea9SToby Isaac PetscAssertPointer(dmParallel, 4); 186770034214SMatthew G. Knepley 18680c86c063SLisandro Dalcin if (sf) *sf = NULL; 18690c86c063SLisandro Dalcin *dmParallel = NULL; 18709566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 18719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 18729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 18733ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 187470034214SMatthew G. Knepley 1875*3b9d9b65SStefano Zampini /* Handle multistage partitioner */ 1876*3b9d9b65SStefano Zampini PetscCall(DMPlexGetPartitioner(dm, &partitioner)); 1877*3b9d9b65SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)partitioner, PETSCPARTITIONERMULTISTAGE, &isms)); 1878*3b9d9b65SStefano Zampini if (isms) { 1879*3b9d9b65SStefano Zampini PetscObject stagedm; 1880*3b9d9b65SStefano Zampini 1881*3b9d9b65SStefano Zampini PetscCall(PetscPartitionerMultistageGetStage_Multistage(partitioner, NULL, &stagedm)); 1882*3b9d9b65SStefano Zampini if (!stagedm) { /* No stage dm present, start the multistage algorithm */ 1883*3b9d9b65SStefano Zampini PetscCall(DMPlexDistribute_Multistage(dm, overlap, sf, dmParallel)); 1884*3b9d9b65SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1885*3b9d9b65SStefano Zampini } 1886*3b9d9b65SStefano Zampini } 18879566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Distribute, dm, 0, 0, 0)); 188815078cd4SMichael Lange /* Create cell partition */ 18899566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0)); 18909566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &cellPartSection)); 18919566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDMPlexPartition(partitioner, dm, NULL, cellPartSection, &cellPart)); 18929566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartSelf, dm, 0, 0, 0)); 1893f8987ae8SMichael Lange { 1894f8987ae8SMichael Lange /* Convert partition to DMLabel */ 1895825f8a23SLisandro Dalcin IS is; 1896825f8a23SLisandro Dalcin PetscHSetI ht; 1897f8987ae8SMichael Lange const PetscInt *points; 18988e330a33SStefano Zampini PetscInt *iranks; 18998e330a33SStefano Zampini PetscInt pStart, pEnd, proc, npoints, poff = 0, nranks; 1900825f8a23SLisandro Dalcin 19019566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point Partition", &lblPartition)); 1902825f8a23SLisandro Dalcin /* Preallocate strata */ 19039566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 19049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1905825f8a23SLisandro Dalcin for (proc = pStart; proc < pEnd; proc++) { 19069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints)); 19079566063dSJacob Faibussowitsch if (npoints) PetscCall(PetscHSetIAdd(ht, proc)); 1908825f8a23SLisandro Dalcin } 19099566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ht, &nranks)); 19109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nranks, &iranks)); 19119566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ht, &poff, iranks)); 19129566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 19139566063dSJacob Faibussowitsch PetscCall(DMLabelAddStrata(lblPartition, nranks, iranks)); 19149566063dSJacob Faibussowitsch PetscCall(PetscFree(iranks)); 1915825f8a23SLisandro Dalcin /* Inline DMPlexPartitionLabelClosure() */ 19169566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellPart, &points)); 19179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1918f8987ae8SMichael Lange for (proc = pStart; proc < pEnd; proc++) { 19199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints)); 1920825f8a23SLisandro Dalcin if (!npoints) continue; 19219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellPartSection, proc, &poff)); 19229566063dSJacob Faibussowitsch PetscCall(DMPlexClosurePoints_Private(dm, npoints, points + poff, &is)); 19239566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(lblPartition, proc, is)); 19249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1925f8987ae8SMichael Lange } 19269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellPart, &points)); 1927f8987ae8SMichael Lange } 19289566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartSelf, dm, 0, 0, 0)); 19296e203dd9SStefano Zampini 19309566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point migration", &lblMigration)); 19319566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelInvert(dm, lblPartition, NULL, lblMigration)); 19323ac0285dSStefano Zampini PetscCall(DMPlexPartitionLabelCreateSF(dm, lblMigration, PETSC_TRUE, &sfMigration)); 19339566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, sfMigration, &sfStratified)); 19349566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration)); 193543f7d02bSMichael Lange sfMigration = sfStratified; 19369566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sfMigration)); 19379566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0)); 19389566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-partition_view", &flg)); 193970034214SMatthew G. Knepley if (flg) { 19409566063dSJacob Faibussowitsch PetscCall(DMLabelView(lblPartition, PETSC_VIEWER_STDOUT_(comm))); 19419566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfMigration, PETSC_VIEWER_STDOUT_(comm))); 194270034214SMatthew G. Knepley } 1943f8987ae8SMichael Lange 194415078cd4SMichael Lange /* Create non-overlapping parallel DM and migrate internal data */ 19459566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, dmParallel)); 19469566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*dmParallel, "Parallel Mesh")); 19479566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(dm, sfMigration, *dmParallel)); 194870034214SMatthew G. Knepley 1949a157612eSMichael Lange /* Build the point SF without overlap */ 19509566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitionBalance(dm, &balance)); 19519566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitionBalance(*dmParallel, balance)); 19529566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*dmParallel, sfMigration, PETSC_TRUE, &sfPoint)); 19539566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*dmParallel, sfPoint)); 19545f06a3ddSJed Brown PetscCall(DMPlexMigrateIsoperiodicFaceSF_Internal(dm, *dmParallel, sfMigration)); 19559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dmParallel, &dmCoord)); 19569566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 19579566063dSJacob Faibussowitsch if (flg) PetscCall(PetscSFView(sfPoint, NULL)); 195870034214SMatthew G. Knepley 1959a157612eSMichael Lange if (overlap > 0) { 196015078cd4SMichael Lange DM dmOverlap; 196115078cd4SMichael Lange PetscSF sfOverlap, sfOverlapPoint; 1962524e35f8SStefano Zampini 1963a157612eSMichael Lange /* Add the partition overlap to the distributed DM */ 19649566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeOverlap(*dmParallel, overlap, &sfOverlap, &dmOverlap)); 19659566063dSJacob Faibussowitsch PetscCall(DMDestroy(dmParallel)); 1966a157612eSMichael Lange *dmParallel = dmOverlap; 1967c389ea9fSToby Isaac if (flg) { 19689566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Overlap Migration SF:\n")); 19699566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfOverlap, NULL)); 1970c389ea9fSToby Isaac } 197143331d4aSMichael Lange 1972f8987ae8SMichael Lange /* Re-map the migration SF to establish the full migration pattern */ 197300a1aa47SMatthew G. Knepley PetscCall(DMPlexRemapMigrationSF(sfOverlap, sfMigration, &sfOverlapPoint)); 19749566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfOverlap)); 19759566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration)); 197615078cd4SMichael Lange sfMigration = sfOverlapPoint; 1977c389ea9fSToby Isaac } 1978bf5244c7SMatthew G. Knepley /* Cleanup Partition */ 19799566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblPartition)); 19809566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblMigration)); 19819566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cellPartSection)); 19829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellPart)); 198312a88998SMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *dmParallel)); 198412a88998SMatthew G. Knepley // Create sfNatural, need discretization information 19859566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *dmParallel)); 19865d2873a6SJames Wright if (dm->localSection) { 19875d2873a6SJames Wright PetscSection psection; 19885d2873a6SJames Wright PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &psection)); 19895d2873a6SJames Wright PetscCall(PetscSFDistributeSection(sfMigration, dm->localSection, NULL, psection)); 19905d2873a6SJames Wright PetscCall(DMSetLocalSection(*dmParallel, psection)); 19915d2873a6SJames Wright PetscCall(PetscSectionDestroy(&psection)); 19925d2873a6SJames Wright } 199366fe0bfeSMatthew G. Knepley if (dm->useNatural) { 199466fe0bfeSMatthew G. Knepley PetscSection section; 199566fe0bfeSMatthew G. Knepley 1996fc6a3818SBlaise Bourdin PetscCall(DMSetUseNatural(*dmParallel, PETSC_TRUE)); 1997fc6a3818SBlaise Bourdin PetscCall(DMGetLocalSection(dm, §ion)); 1998fc6a3818SBlaise Bourdin 199916635c05SJames Wright /* If DM has useNatural = PETSC_TRUE, but no sfNatural is set, the DM's Section is considered natural */ 20008aee0f92SAlexis Marboeuf /* sfMigration and sfNatural are respectively the point and dofs SFs mapping to this natural DM */ 2001fc6a3818SBlaise Bourdin /* Compose with a previous sfNatural if present */ 2002fc6a3818SBlaise Bourdin if (dm->sfNatural) { 200316635c05SJames Wright PetscCall(DMPlexMigrateGlobalToNaturalSF(dm, *dmParallel, dm->sfNatural, sfMigration, &(*dmParallel)->sfNatural)); 2004fc6a3818SBlaise Bourdin } else { 2005fc6a3818SBlaise Bourdin PetscCall(DMPlexCreateGlobalToNaturalSF(*dmParallel, section, sfMigration, &(*dmParallel)->sfNatural)); 2006fc6a3818SBlaise Bourdin } 20078aee0f92SAlexis Marboeuf /* Compose with a previous sfMigration if present */ 20088aee0f92SAlexis Marboeuf if (dm->sfMigration) { 20098aee0f92SAlexis Marboeuf PetscSF naturalPointSF; 20108aee0f92SAlexis Marboeuf 20118aee0f92SAlexis Marboeuf PetscCall(PetscSFCompose(dm->sfMigration, sfMigration, &naturalPointSF)); 20128aee0f92SAlexis Marboeuf PetscCall(PetscSFDestroy(&sfMigration)); 20138aee0f92SAlexis Marboeuf sfMigration = naturalPointSF; 20148aee0f92SAlexis Marboeuf } 201566fe0bfeSMatthew G. Knepley } 2016721cbd76SMatthew G. Knepley /* Cleanup */ 20179371c9d4SSatish Balay if (sf) { 20189371c9d4SSatish Balay *sf = sfMigration; 20199371c9d4SSatish Balay } else PetscCall(PetscSFDestroy(&sfMigration)); 20209566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 20219566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Distribute, dm, 0, 0, 0)); 20223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 202370034214SMatthew G. Knepley } 2024a157612eSMichael Lange 2025907a3e9cSStefano Zampini PetscErrorCode DMPlexDistributeOverlap_Internal(DM dm, PetscInt overlap, MPI_Comm newcomm, const char *ovlboundary, PetscSF *sf, DM *dmOverlap) 2026907a3e9cSStefano Zampini { 2027907a3e9cSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 2028907a3e9cSStefano Zampini MPI_Comm comm; 2029907a3e9cSStefano Zampini PetscMPIInt size, rank; 2030907a3e9cSStefano Zampini PetscSection rootSection, leafSection; 2031907a3e9cSStefano Zampini IS rootrank, leafrank; 2032907a3e9cSStefano Zampini DM dmCoord; 2033907a3e9cSStefano Zampini DMLabel lblOverlap; 2034907a3e9cSStefano Zampini PetscSF sfOverlap, sfStratified, sfPoint; 2035907a3e9cSStefano Zampini PetscBool clear_ovlboundary; 2036907a3e9cSStefano Zampini 2037907a3e9cSStefano Zampini PetscFunctionBegin; 2038907a3e9cSStefano Zampini if (sf) *sf = NULL; 2039907a3e9cSStefano Zampini *dmOverlap = NULL; 2040907a3e9cSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 2041907a3e9cSStefano Zampini PetscCallMPI(MPI_Comm_size(comm, &size)); 2042907a3e9cSStefano Zampini PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2043907a3e9cSStefano Zampini if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 2044907a3e9cSStefano Zampini { 2045907a3e9cSStefano Zampini // We need to get options for the _already_distributed mesh, so it must be done here 2046907a3e9cSStefano Zampini PetscInt overlap; 2047907a3e9cSStefano Zampini const char *prefix; 2048907a3e9cSStefano Zampini char oldPrefix[PETSC_MAX_PATH_LEN]; 2049907a3e9cSStefano Zampini 2050907a3e9cSStefano Zampini oldPrefix[0] = '\0'; 2051907a3e9cSStefano Zampini PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 2052907a3e9cSStefano Zampini PetscCall(PetscStrncpy(oldPrefix, prefix, sizeof(oldPrefix))); 2053907a3e9cSStefano Zampini PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, "dist_")); 2054907a3e9cSStefano Zampini PetscCall(DMPlexGetOverlap(dm, &overlap)); 2055907a3e9cSStefano Zampini PetscObjectOptionsBegin((PetscObject)dm); 2056907a3e9cSStefano Zampini PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 2057907a3e9cSStefano Zampini PetscOptionsEnd(); 2058907a3e9cSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix[0] == '\0' ? NULL : oldPrefix)); 2059907a3e9cSStefano Zampini } 2060907a3e9cSStefano Zampini if (ovlboundary) { 2061907a3e9cSStefano Zampini PetscBool flg; 2062907a3e9cSStefano Zampini PetscCall(DMHasLabel(dm, ovlboundary, &flg)); 2063907a3e9cSStefano Zampini if (!flg) { 2064907a3e9cSStefano Zampini DMLabel label; 2065907a3e9cSStefano Zampini 2066907a3e9cSStefano Zampini PetscCall(DMCreateLabel(dm, ovlboundary)); 2067907a3e9cSStefano Zampini PetscCall(DMGetLabel(dm, ovlboundary, &label)); 2068907a3e9cSStefano Zampini PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label)); 2069907a3e9cSStefano Zampini clear_ovlboundary = PETSC_TRUE; 2070907a3e9cSStefano Zampini } 2071907a3e9cSStefano Zampini } 2072907a3e9cSStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 2073907a3e9cSStefano Zampini /* Compute point overlap with neighbouring processes on the distributed DM */ 2074907a3e9cSStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0)); 2075907a3e9cSStefano Zampini PetscCall(PetscSectionCreate(newcomm, &rootSection)); 2076907a3e9cSStefano Zampini PetscCall(PetscSectionCreate(newcomm, &leafSection)); 2077907a3e9cSStefano Zampini PetscCall(DMPlexDistributeOwnership(dm, rootSection, &rootrank, leafSection, &leafrank)); 2078907a3e9cSStefano Zampini if (mesh->numOvLabels) PetscCall(DMPlexCreateOverlapLabelFromLabels(dm, mesh->numOvLabels, mesh->ovLabels, mesh->ovValues, mesh->numOvExLabels, mesh->ovExLabels, mesh->ovExValues, rootSection, rootrank, leafSection, leafrank, &lblOverlap)); 2079907a3e9cSStefano Zampini else PetscCall(DMPlexCreateOverlapLabel(dm, overlap, rootSection, rootrank, leafSection, leafrank, &lblOverlap)); 2080907a3e9cSStefano Zampini /* Convert overlap label to stratified migration SF */ 20813ac0285dSStefano Zampini PetscCall(DMPlexPartitionLabelCreateSF(dm, lblOverlap, PETSC_FALSE, &sfOverlap)); 2082907a3e9cSStefano Zampini PetscCall(DMPlexStratifyMigrationSF(dm, sfOverlap, &sfStratified)); 2083907a3e9cSStefano Zampini PetscCall(PetscSFDestroy(&sfOverlap)); 2084907a3e9cSStefano Zampini sfOverlap = sfStratified; 2085907a3e9cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)sfOverlap, "Overlap SF")); 2086907a3e9cSStefano Zampini PetscCall(PetscSFSetFromOptions(sfOverlap)); 2087907a3e9cSStefano Zampini 2088907a3e9cSStefano Zampini PetscCall(PetscSectionDestroy(&rootSection)); 2089907a3e9cSStefano Zampini PetscCall(PetscSectionDestroy(&leafSection)); 2090907a3e9cSStefano Zampini PetscCall(ISDestroy(&rootrank)); 2091907a3e9cSStefano Zampini PetscCall(ISDestroy(&leafrank)); 2092907a3e9cSStefano Zampini PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0)); 2093907a3e9cSStefano Zampini 2094907a3e9cSStefano Zampini /* Build the overlapping DM */ 2095907a3e9cSStefano Zampini PetscCall(DMPlexCreate(newcomm, dmOverlap)); 2096907a3e9cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*dmOverlap, "Parallel Mesh")); 2097907a3e9cSStefano Zampini PetscCall(DMPlexMigrate(dm, sfOverlap, *dmOverlap)); 2098907a3e9cSStefano Zampini /* Store the overlap in the new DM */ 2099907a3e9cSStefano Zampini PetscCall(DMPlexSetOverlap_Plex(*dmOverlap, dm, overlap)); 2100907a3e9cSStefano Zampini /* Build the new point SF */ 2101907a3e9cSStefano Zampini PetscCall(DMPlexCreatePointSF(*dmOverlap, sfOverlap, PETSC_FALSE, &sfPoint)); 2102907a3e9cSStefano Zampini PetscCall(DMSetPointSF(*dmOverlap, sfPoint)); 2103907a3e9cSStefano Zampini PetscCall(DMGetCoordinateDM(*dmOverlap, &dmCoord)); 2104907a3e9cSStefano Zampini if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 2105907a3e9cSStefano Zampini PetscCall(DMGetCellCoordinateDM(*dmOverlap, &dmCoord)); 2106907a3e9cSStefano Zampini if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 2107907a3e9cSStefano Zampini PetscCall(PetscSFDestroy(&sfPoint)); 2108907a3e9cSStefano Zampini PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *dmOverlap)); 2109907a3e9cSStefano Zampini /* TODO: labels stored inside the DS for regions should be handled here */ 2110907a3e9cSStefano Zampini PetscCall(DMCopyDisc(dm, *dmOverlap)); 2111907a3e9cSStefano Zampini /* Cleanup overlap partition */ 2112907a3e9cSStefano Zampini PetscCall(DMLabelDestroy(&lblOverlap)); 2113907a3e9cSStefano Zampini if (sf) *sf = sfOverlap; 2114907a3e9cSStefano Zampini else PetscCall(PetscSFDestroy(&sfOverlap)); 2115907a3e9cSStefano Zampini if (ovlboundary) { 2116907a3e9cSStefano Zampini DMLabel label; 2117907a3e9cSStefano Zampini PetscBool flg; 2118907a3e9cSStefano Zampini 2119907a3e9cSStefano Zampini if (clear_ovlboundary) PetscCall(DMRemoveLabel(dm, ovlboundary, NULL)); 2120907a3e9cSStefano Zampini PetscCall(DMHasLabel(*dmOverlap, ovlboundary, &flg)); 212100045ab3SPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing %s label", ovlboundary); 2122907a3e9cSStefano Zampini PetscCall(DMGetLabel(*dmOverlap, ovlboundary, &label)); 2123907a3e9cSStefano Zampini PetscCall(DMPlexMarkBoundaryFaces_Internal(*dmOverlap, 1, 0, label, PETSC_TRUE)); 2124907a3e9cSStefano Zampini } 2125907a3e9cSStefano Zampini PetscCall(PetscLogEventEnd(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 2126907a3e9cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2127907a3e9cSStefano Zampini } 2128907a3e9cSStefano Zampini 21295d83a8b1SBarry Smith /*@ 213020f4b53cSBarry Smith DMPlexDistributeOverlap - Add partition overlap to a distributed non-overlapping `DM`. 2131a157612eSMichael Lange 213220f4b53cSBarry Smith Collective 2133a157612eSMichael Lange 2134064ec1f3Sprj- Input Parameters: 213520f4b53cSBarry Smith + dm - The non-overlapping distributed `DMPLEX` object 213657fe9a49SVaclav Hapla - overlap - The overlap of partitions (the same on all ranks) 2137a157612eSMichael Lange 2138064ec1f3Sprj- Output Parameters: 2139f13dfd9eSBarry Smith + sf - The `PetscSF` used for point distribution, or pass `NULL` if not needed 2140f13dfd9eSBarry Smith - dmOverlap - The overlapping distributed `DMPLEX` object 2141a157612eSMichael Lange 2142c506a872SMatthew G. Knepley Options Database Keys: 2143c506a872SMatthew G. Knepley + -dm_plex_overlap_labels <name1,name2,...> - List of overlap label names 2144c506a872SMatthew G. Knepley . -dm_plex_overlap_values <int1,int2,...> - List of overlap label values 2145c506a872SMatthew G. Knepley . -dm_plex_overlap_exclude_label <name> - Label used to exclude points from overlap 2146c506a872SMatthew G. Knepley - -dm_plex_overlap_exclude_value <int> - Label value used to exclude points from overlap 2147c506a872SMatthew G. Knepley 2148dccdeccaSVaclav Hapla Level: advanced 2149a157612eSMichael Lange 215020f4b53cSBarry Smith Notes: 215120f4b53cSBarry Smith If the mesh was not distributed, the return value is `NULL`. 215220f4b53cSBarry Smith 215320f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function 215420f4b53cSBarry Smith representation on the mesh. 215520f4b53cSBarry Smith 215620f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMPlexCreateOverlapLabel()`, `DMPlexGetOverlap()` 2157a157612eSMichael Lange @*/ 2158ce78bad3SBarry Smith PetscErrorCode DMPlexDistributeOverlap(DM dm, PetscInt overlap, PeOp PetscSF *sf, DM *dmOverlap) 2159d71ae5a4SJacob Faibussowitsch { 2160a157612eSMichael Lange PetscFunctionBegin; 2161a157612eSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 216257fe9a49SVaclav Hapla PetscValidLogicalCollectiveInt(dm, overlap, 2); 21634f572ea9SToby Isaac if (sf) PetscAssertPointer(sf, 3); 21644f572ea9SToby Isaac PetscAssertPointer(dmOverlap, 4); 2165907a3e9cSStefano Zampini PetscCall(DMPlexDistributeOverlap_Internal(dm, overlap, PetscObjectComm((PetscObject)dm), NULL, sf, dmOverlap)); 21663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2167a157612eSMichael Lange } 21686462276dSToby Isaac 2169d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap_Plex(DM dm, PetscInt *overlap) 2170d71ae5a4SJacob Faibussowitsch { 2171cb54e036SVaclav Hapla DM_Plex *mesh = (DM_Plex *)dm->data; 2172cb54e036SVaclav Hapla 2173cb54e036SVaclav Hapla PetscFunctionBegin; 2174cb54e036SVaclav Hapla *overlap = mesh->overlap; 21753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2176cb54e036SVaclav Hapla } 2177cb54e036SVaclav Hapla 2178d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap_Plex(DM dm, DM dmSrc, PetscInt overlap) 2179d71ae5a4SJacob Faibussowitsch { 218060667520SVaclav Hapla DM_Plex *mesh = NULL; 218160667520SVaclav Hapla DM_Plex *meshSrc = NULL; 218260667520SVaclav Hapla 218360667520SVaclav Hapla PetscFunctionBegin; 218460667520SVaclav Hapla PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 218560667520SVaclav Hapla mesh = (DM_Plex *)dm->data; 218660667520SVaclav Hapla if (dmSrc) { 218760667520SVaclav Hapla PetscValidHeaderSpecificType(dmSrc, DM_CLASSID, 2, DMPLEX); 218860667520SVaclav Hapla meshSrc = (DM_Plex *)dmSrc->data; 21899ed9361bSToby Isaac mesh->overlap = meshSrc->overlap; 21909ed9361bSToby Isaac } else { 21919ed9361bSToby Isaac mesh->overlap = 0; 219260667520SVaclav Hapla } 21939ed9361bSToby Isaac mesh->overlap += overlap; 21943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 219560667520SVaclav Hapla } 219660667520SVaclav Hapla 2197cb54e036SVaclav Hapla /*@ 2198c506a872SMatthew G. Knepley DMPlexGetOverlap - Get the width of the cell overlap 2199cb54e036SVaclav Hapla 220020f4b53cSBarry Smith Not Collective 2201cb54e036SVaclav Hapla 2202cb54e036SVaclav Hapla Input Parameter: 220320f4b53cSBarry Smith . dm - The `DM` 2204cb54e036SVaclav Hapla 2205064ec1f3Sprj- Output Parameter: 2206c506a872SMatthew G. Knepley . overlap - the width of the cell overlap 2207cb54e036SVaclav Hapla 2208cb54e036SVaclav Hapla Level: intermediate 2209cb54e036SVaclav Hapla 221020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexSetOverlap()`, `DMPlexDistribute()` 2211cb54e036SVaclav Hapla @*/ 2212d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap(DM dm, PetscInt *overlap) 2213d71ae5a4SJacob Faibussowitsch { 2214cb54e036SVaclav Hapla PetscFunctionBegin; 2215cb54e036SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22164f572ea9SToby Isaac PetscAssertPointer(overlap, 2); 2217cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexGetOverlap_C", (DM, PetscInt *), (dm, overlap)); 22183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2219cb54e036SVaclav Hapla } 2220cb54e036SVaclav Hapla 2221c506a872SMatthew G. Knepley /*@ 2222c506a872SMatthew G. Knepley DMPlexSetOverlap - Set the width of the cell overlap 2223c506a872SMatthew G. Knepley 222420f4b53cSBarry Smith Logically Collective 2225c506a872SMatthew G. Knepley 2226c506a872SMatthew G. Knepley Input Parameters: 222720f4b53cSBarry Smith + dm - The `DM` 222820f4b53cSBarry Smith . dmSrc - The `DM` that produced this one, or `NULL` 2229c506a872SMatthew G. Knepley - overlap - the width of the cell overlap 2230c506a872SMatthew G. Knepley 2231c506a872SMatthew G. Knepley Level: intermediate 2232c506a872SMatthew G. Knepley 223320f4b53cSBarry Smith Note: 223420f4b53cSBarry Smith The overlap from `dmSrc` is added to `dm` 223520f4b53cSBarry Smith 223620f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexGetOverlap()`, `DMPlexDistribute()` 2237c506a872SMatthew G. Knepley @*/ 2238d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap(DM dm, DM dmSrc, PetscInt overlap) 2239d71ae5a4SJacob Faibussowitsch { 2240c506a872SMatthew G. Knepley PetscFunctionBegin; 2241c506a872SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2242c506a872SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 3); 2243c506a872SMatthew G. Knepley PetscTryMethod(dm, "DMPlexSetOverlap_C", (DM, DM, PetscInt), (dm, dmSrc, overlap)); 22443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2245c506a872SMatthew G. Knepley } 2246c506a872SMatthew G. Knepley 2247d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault_Plex(DM dm, PetscBool dist) 2248d71ae5a4SJacob Faibussowitsch { 2249e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2250e600fa54SMatthew G. Knepley 2251e600fa54SMatthew G. Knepley PetscFunctionBegin; 2252e600fa54SMatthew G. Knepley mesh->distDefault = dist; 22533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2254e600fa54SMatthew G. Knepley } 2255e600fa54SMatthew G. Knepley 2256e600fa54SMatthew G. Knepley /*@ 225720f4b53cSBarry Smith DMPlexDistributeSetDefault - Set flag indicating whether the `DM` should be distributed by default 2258e600fa54SMatthew G. Knepley 225920f4b53cSBarry Smith Logically Collective 2260e600fa54SMatthew G. Knepley 2261e600fa54SMatthew G. Knepley Input Parameters: 226220f4b53cSBarry Smith + dm - The `DM` 2263e600fa54SMatthew G. Knepley - dist - Flag for distribution 2264e600fa54SMatthew G. Knepley 2265e600fa54SMatthew G. Knepley Level: intermediate 2266e600fa54SMatthew G. Knepley 226720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributeGetDefault()`, `DMPlexDistribute()` 2268e600fa54SMatthew G. Knepley @*/ 2269d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault(DM dm, PetscBool dist) 2270d71ae5a4SJacob Faibussowitsch { 2271e600fa54SMatthew G. Knepley PetscFunctionBegin; 2272e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2273e600fa54SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, dist, 2); 2274cac4c232SBarry Smith PetscTryMethod(dm, "DMPlexDistributeSetDefault_C", (DM, PetscBool), (dm, dist)); 22753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2276e600fa54SMatthew G. Knepley } 2277e600fa54SMatthew G. Knepley 2278d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault_Plex(DM dm, PetscBool *dist) 2279d71ae5a4SJacob Faibussowitsch { 2280e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2281e600fa54SMatthew G. Knepley 2282e600fa54SMatthew G. Knepley PetscFunctionBegin; 2283e600fa54SMatthew G. Knepley *dist = mesh->distDefault; 22843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2285e600fa54SMatthew G. Knepley } 2286e600fa54SMatthew G. Knepley 2287e600fa54SMatthew G. Knepley /*@ 228820f4b53cSBarry Smith DMPlexDistributeGetDefault - Get flag indicating whether the `DM` should be distributed by default 2289e600fa54SMatthew G. Knepley 229020f4b53cSBarry Smith Not Collective 2291e600fa54SMatthew G. Knepley 2292e600fa54SMatthew G. Knepley Input Parameter: 229320f4b53cSBarry Smith . dm - The `DM` 2294e600fa54SMatthew G. Knepley 2295e600fa54SMatthew G. Knepley Output Parameter: 2296e600fa54SMatthew G. Knepley . dist - Flag for distribution 2297e600fa54SMatthew G. Knepley 2298e600fa54SMatthew G. Knepley Level: intermediate 2299e600fa54SMatthew G. Knepley 230020f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexDistributeSetDefault()`, `DMPlexDistribute()` 2301e600fa54SMatthew G. Knepley @*/ 2302d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault(DM dm, PetscBool *dist) 2303d71ae5a4SJacob Faibussowitsch { 2304e600fa54SMatthew G. Knepley PetscFunctionBegin; 2305e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23064f572ea9SToby Isaac PetscAssertPointer(dist, 2); 2307cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexDistributeGetDefault_C", (DM, PetscBool *), (dm, dist)); 23083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2309e600fa54SMatthew G. Knepley } 2310e600fa54SMatthew G. Knepley 2311ce78bad3SBarry Smith /*@ 231220f4b53cSBarry Smith DMPlexGetGatherDM - Get a copy of the `DMPLEX` that gathers all points on the 23136462276dSToby Isaac root process of the original's communicator. 23146462276dSToby Isaac 231520f4b53cSBarry Smith Collective 231683655b49SVáclav Hapla 2317064ec1f3Sprj- Input Parameter: 231820f4b53cSBarry Smith . dm - the original `DMPLEX` object 23196462276dSToby Isaac 23206462276dSToby Isaac Output Parameters: 232120f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional) 232220f4b53cSBarry Smith - gatherMesh - the gathered `DM` object, or `NULL` 23236462276dSToby Isaac 23246462276dSToby Isaac Level: intermediate 23256462276dSToby Isaac 232620f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `PetscSF`, `DMPlexDistribute()`, `DMPlexGetRedundantDM()` 23276462276dSToby Isaac @*/ 2328ce78bad3SBarry Smith PetscErrorCode DMPlexGetGatherDM(DM dm, PetscSF *sf, PeOp DM *gatherMesh) 2329d71ae5a4SJacob Faibussowitsch { 23306462276dSToby Isaac MPI_Comm comm; 23316462276dSToby Isaac PetscMPIInt size; 23326462276dSToby Isaac PetscPartitioner oldPart, gatherPart; 23336462276dSToby Isaac 23346462276dSToby Isaac PetscFunctionBegin; 23356462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23364f572ea9SToby Isaac PetscAssertPointer(gatherMesh, 3); 23370c86c063SLisandro Dalcin *gatherMesh = NULL; 2338a13df41bSStefano Zampini if (sf) *sf = NULL; 23396462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 23409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 23413ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 23429566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &oldPart)); 23439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)oldPart)); 23449566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(comm, &gatherPart)); 23459566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetType(gatherPart, PETSCPARTITIONERGATHER)); 23469566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, gatherPart)); 23479566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, sf, gatherMesh)); 2348a13df41bSStefano Zampini 23499566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, oldPart)); 23509566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&gatherPart)); 23519566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&oldPart)); 23523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23536462276dSToby Isaac } 23546462276dSToby Isaac 2355ce78bad3SBarry Smith /*@ 235620f4b53cSBarry Smith DMPlexGetRedundantDM - Get a copy of the `DMPLEX` that is completely copied on each process. 23576462276dSToby Isaac 235820f4b53cSBarry Smith Collective 235983655b49SVáclav Hapla 2360064ec1f3Sprj- Input Parameter: 236120f4b53cSBarry Smith . dm - the original `DMPLEX` object 23626462276dSToby Isaac 23636462276dSToby Isaac Output Parameters: 236420f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional) 236520f4b53cSBarry Smith - redundantMesh - the redundant `DM` object, or `NULL` 23666462276dSToby Isaac 23676462276dSToby Isaac Level: intermediate 23686462276dSToby Isaac 236960225df5SJacob Faibussowitsch .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetGatherDM()` 23706462276dSToby Isaac @*/ 2371ce78bad3SBarry Smith PetscErrorCode DMPlexGetRedundantDM(DM dm, PetscSF *sf, PeOp DM *redundantMesh) 2372d71ae5a4SJacob Faibussowitsch { 23736462276dSToby Isaac MPI_Comm comm; 23746462276dSToby Isaac PetscMPIInt size, rank; 23756462276dSToby Isaac PetscInt pStart, pEnd, p; 23766462276dSToby Isaac PetscInt numPoints = -1; 2377a13df41bSStefano Zampini PetscSF migrationSF, sfPoint, gatherSF; 23786462276dSToby Isaac DM gatherDM, dmCoord; 23796462276dSToby Isaac PetscSFNode *points; 23806462276dSToby Isaac 23816462276dSToby Isaac PetscFunctionBegin; 23826462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23834f572ea9SToby Isaac PetscAssertPointer(redundantMesh, 3); 23840c86c063SLisandro Dalcin *redundantMesh = NULL; 23856462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 23869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 238768dbc166SMatthew G. Knepley if (size == 1) { 23889566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 238968dbc166SMatthew G. Knepley *redundantMesh = dm; 2390a13df41bSStefano Zampini if (sf) *sf = NULL; 23913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 239268dbc166SMatthew G. Knepley } 23939566063dSJacob Faibussowitsch PetscCall(DMPlexGetGatherDM(dm, &gatherSF, &gatherDM)); 23943ba16761SJacob Faibussowitsch if (!gatherDM) PetscFunctionReturn(PETSC_SUCCESS); 23959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 23969566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(gatherDM, &pStart, &pEnd)); 23976462276dSToby Isaac numPoints = pEnd - pStart; 23989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numPoints, 1, MPIU_INT, 0, comm)); 23999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &points)); 24009566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &migrationSF)); 24016462276dSToby Isaac for (p = 0; p < numPoints; p++) { 24026462276dSToby Isaac points[p].index = p; 24036462276dSToby Isaac points[p].rank = 0; 24046462276dSToby Isaac } 24059566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(migrationSF, pEnd - pStart, numPoints, NULL, PETSC_OWN_POINTER, points, PETSC_OWN_POINTER)); 24069566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, redundantMesh)); 24079566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*redundantMesh, "Redundant Mesh")); 24089566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(gatherDM, migrationSF, *redundantMesh)); 24092e28cf0cSVaclav Hapla /* This is to express that all point are in overlap */ 24101690c2aeSBarry Smith PetscCall(DMPlexSetOverlap_Plex(*redundantMesh, NULL, PETSC_INT_MAX)); 24119566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*redundantMesh, migrationSF, PETSC_FALSE, &sfPoint)); 24129566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*redundantMesh, sfPoint)); 24139566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*redundantMesh, &dmCoord)); 24149566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 24159566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 2416a13df41bSStefano Zampini if (sf) { 2417a13df41bSStefano Zampini PetscSF tsf; 2418a13df41bSStefano Zampini 24199566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(gatherSF, migrationSF, &tsf)); 24209566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, tsf, sf)); 24219566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&tsf)); 2422a13df41bSStefano Zampini } 24239566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&migrationSF)); 24249566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&gatherSF)); 24259566063dSJacob Faibussowitsch PetscCall(DMDestroy(&gatherDM)); 24269566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *redundantMesh)); 24275de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *redundantMesh)); 24283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24296462276dSToby Isaac } 24305fa78c88SVaclav Hapla 24315fa78c88SVaclav Hapla /*@ 243220f4b53cSBarry Smith DMPlexIsDistributed - Find out whether this `DM` is distributed, i.e. more than one rank owns some points. 24335fa78c88SVaclav Hapla 24345fa78c88SVaclav Hapla Collective 24355fa78c88SVaclav Hapla 24365fa78c88SVaclav Hapla Input Parameter: 243720f4b53cSBarry Smith . dm - The `DM` object 24385fa78c88SVaclav Hapla 24395fa78c88SVaclav Hapla Output Parameter: 244020f4b53cSBarry Smith . distributed - Flag whether the `DM` is distributed 24415fa78c88SVaclav Hapla 24425fa78c88SVaclav Hapla Level: intermediate 24435fa78c88SVaclav Hapla 24445fa78c88SVaclav Hapla Notes: 24455fa78c88SVaclav Hapla This currently finds out whether at least two ranks have any DAG points. 244620f4b53cSBarry Smith This involves `MPI_Allreduce()` with one integer. 24475fa78c88SVaclav Hapla The result is currently not stashed so every call to this routine involves this global communication. 24485fa78c88SVaclav Hapla 244960225df5SJacob Faibussowitsch .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetOverlap()`, `DMPlexIsInterpolated()` 24505fa78c88SVaclav Hapla @*/ 2451d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsDistributed(DM dm, PetscBool *distributed) 2452d71ae5a4SJacob Faibussowitsch { 24535fa78c88SVaclav Hapla PetscInt pStart, pEnd, count; 24545fa78c88SVaclav Hapla MPI_Comm comm; 245535d70e31SStefano Zampini PetscMPIInt size; 24565fa78c88SVaclav Hapla 24575fa78c88SVaclav Hapla PetscFunctionBegin; 24585fa78c88SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24594f572ea9SToby Isaac PetscAssertPointer(distributed, 2); 24609566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 24619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 24629371c9d4SSatish Balay if (size == 1) { 24639371c9d4SSatish Balay *distributed = PETSC_FALSE; 24643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24659371c9d4SSatish Balay } 24669566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 246735d70e31SStefano Zampini count = (pEnd - pStart) > 0 ? 1 : 0; 2468462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &count, 1, MPIU_INT, MPI_SUM, comm)); 24695fa78c88SVaclav Hapla *distributed = count > 1 ? PETSC_TRUE : PETSC_FALSE; 24703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24715fa78c88SVaclav Hapla } 24721d1f2f2aSksagiyam 2473cc4c1da9SBarry Smith /*@ 24741d1f2f2aSksagiyam DMPlexDistributionSetName - Set the name of the specific parallel distribution 24751d1f2f2aSksagiyam 24761d1f2f2aSksagiyam Input Parameters: 247720f4b53cSBarry Smith + dm - The `DM` 24781d1f2f2aSksagiyam - name - The name of the specific parallel distribution 24791d1f2f2aSksagiyam 24801d1f2f2aSksagiyam Level: developer 24811d1f2f2aSksagiyam 248220f4b53cSBarry Smith Note: 248320f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's 248420f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under 248520f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()` 248620f4b53cSBarry Smith loads the parallel distribution stored in file under this name. 248720f4b53cSBarry Smith 248820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionGetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()` 24891d1f2f2aSksagiyam @*/ 2490d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionSetName(DM dm, const char name[]) 2491d71ae5a4SJacob Faibussowitsch { 24921d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data; 24931d1f2f2aSksagiyam 24941d1f2f2aSksagiyam PetscFunctionBegin; 24951d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 24964f572ea9SToby Isaac if (name) PetscAssertPointer(name, 2); 24971d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 24981d1f2f2aSksagiyam PetscCall(PetscStrallocpy(name, &mesh->distributionName)); 24993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25001d1f2f2aSksagiyam } 25011d1f2f2aSksagiyam 2502cc4c1da9SBarry Smith /*@ 25031d1f2f2aSksagiyam DMPlexDistributionGetName - Retrieve the name of the specific parallel distribution 25041d1f2f2aSksagiyam 25051d1f2f2aSksagiyam Input Parameter: 250620f4b53cSBarry Smith . dm - The `DM` 25071d1f2f2aSksagiyam 25081d1f2f2aSksagiyam Output Parameter: 25091d1f2f2aSksagiyam . name - The name of the specific parallel distribution 25101d1f2f2aSksagiyam 25111d1f2f2aSksagiyam Level: developer 25121d1f2f2aSksagiyam 251320f4b53cSBarry Smith Note: 251420f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's 251520f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under 251620f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()` 251720f4b53cSBarry Smith loads the parallel distribution stored in file under this name. 251820f4b53cSBarry Smith 251920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionSetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()` 25201d1f2f2aSksagiyam @*/ 2521d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionGetName(DM dm, const char *name[]) 2522d71ae5a4SJacob Faibussowitsch { 25231d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data; 25241d1f2f2aSksagiyam 25251d1f2f2aSksagiyam PetscFunctionBegin; 25261d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 25274f572ea9SToby Isaac PetscAssertPointer(name, 2); 25281d1f2f2aSksagiyam *name = mesh->distributionName; 25293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25301d1f2f2aSksagiyam } 2531