1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/ 370034214SMatthew G. Knepley 43c1f0c11SLawrence Mitchell /*@C 53c1f0c11SLawrence Mitchell DMPlexSetAdjacencyUser - Define adjacency in the mesh using a user-provided callback 63c1f0c11SLawrence Mitchell 73c1f0c11SLawrence Mitchell Input Parameters: 83c1f0c11SLawrence Mitchell + dm - The DM object 920f4b53cSBarry Smith . user - The user callback, may be `NULL` (to clear the callback) 1020f4b53cSBarry Smith - ctx - context for callback evaluation, may be `NULL` 113c1f0c11SLawrence Mitchell 123c1f0c11SLawrence Mitchell Level: advanced 133c1f0c11SLawrence Mitchell 143c1f0c11SLawrence Mitchell Notes: 1520f4b53cSBarry Smith The caller of `DMPlexGetAdjacency()` may need to arrange that a large enough array is available for the adjacency. 163c1f0c11SLawrence Mitchell 1720f4b53cSBarry Smith Any setting here overrides other configuration of `DMPLEX` adjacency determination. 183c1f0c11SLawrence Mitchell 1920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMPlexPreallocateOperator()`, `DMPlexGetAdjacency()`, `DMPlexGetAdjacencyUser()` 203c1f0c11SLawrence Mitchell @*/ 21d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAdjacencyUser(DM dm, PetscErrorCode (*user)(DM, PetscInt, PetscInt *, PetscInt[], void *), void *ctx) 22d71ae5a4SJacob Faibussowitsch { 233c1f0c11SLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 243c1f0c11SLawrence Mitchell 253c1f0c11SLawrence Mitchell PetscFunctionBegin; 263c1f0c11SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 273c1f0c11SLawrence Mitchell mesh->useradjacency = user; 283c1f0c11SLawrence Mitchell mesh->useradjacencyctx = ctx; 293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 303c1f0c11SLawrence Mitchell } 313c1f0c11SLawrence Mitchell 323c1f0c11SLawrence Mitchell /*@C 333c1f0c11SLawrence Mitchell DMPlexGetAdjacencyUser - get the user-defined adjacency callback 343c1f0c11SLawrence Mitchell 353c1f0c11SLawrence Mitchell Input Parameter: 3620f4b53cSBarry Smith . dm - The `DM` object 373c1f0c11SLawrence Mitchell 383c1f0c11SLawrence Mitchell Output Parameters: 39ef1023bdSBarry Smith + user - The callback 403c1f0c11SLawrence Mitchell - ctx - context for callback evaluation 413c1f0c11SLawrence Mitchell 423c1f0c11SLawrence Mitchell Level: advanced 433c1f0c11SLawrence Mitchell 4420f4b53cSBarry Smith .seealso: `DMPLEX`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMPlexPreallocateOperator()`, `DMPlexGetAdjacency()`, `DMPlexSetAdjacencyUser()` 453c1f0c11SLawrence Mitchell @*/ 46d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAdjacencyUser(DM dm, PetscErrorCode (**user)(DM, PetscInt, PetscInt *, PetscInt[], void *), void **ctx) 47d71ae5a4SJacob Faibussowitsch { 483c1f0c11SLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 493c1f0c11SLawrence Mitchell 503c1f0c11SLawrence Mitchell PetscFunctionBegin; 513c1f0c11SLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 523c1f0c11SLawrence Mitchell if (user) *user = mesh->useradjacency; 533c1f0c11SLawrence Mitchell if (ctx) *ctx = mesh->useradjacencyctx; 543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 553c1f0c11SLawrence Mitchell } 563c1f0c11SLawrence Mitchell 5770034214SMatthew G. Knepley /*@ 58a17985deSToby Isaac DMPlexSetAdjacencyUseAnchors - Define adjacency in the mesh using the point-to-point constraints. 598b0b4c70SToby Isaac 608b0b4c70SToby Isaac Input Parameters: 6120f4b53cSBarry Smith + dm - The `DM` object 625b317d89SToby Isaac - useAnchors - Flag to use the constraints. If PETSC_TRUE, then constrained points are omitted from DMPlexGetAdjacency(), and their anchor points appear in their place. 638b0b4c70SToby Isaac 648b0b4c70SToby Isaac Level: intermediate 658b0b4c70SToby Isaac 6620f4b53cSBarry Smith .seealso: `DMPLEX`, `DMGetAdjacency()`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMPlexPreallocateOperator()`, `DMPlexSetAnchors()` 678b0b4c70SToby Isaac @*/ 68d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAdjacencyUseAnchors(DM dm, PetscBool useAnchors) 69d71ae5a4SJacob Faibussowitsch { 708b0b4c70SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 718b0b4c70SToby Isaac 728b0b4c70SToby Isaac PetscFunctionBegin; 738b0b4c70SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 745b317d89SToby Isaac mesh->useAnchors = useAnchors; 753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 768b0b4c70SToby Isaac } 778b0b4c70SToby Isaac 788b0b4c70SToby Isaac /*@ 79a17985deSToby Isaac DMPlexGetAdjacencyUseAnchors - Query whether adjacency in the mesh uses the point-to-point constraints. 808b0b4c70SToby Isaac 818b0b4c70SToby Isaac Input Parameter: 8220f4b53cSBarry Smith . dm - The `DM` object 838b0b4c70SToby Isaac 848b0b4c70SToby Isaac Output Parameter: 855b317d89SToby Isaac . useAnchors - Flag to use the closure. If PETSC_TRUE, then constrained points are omitted from DMPlexGetAdjacency(), and their anchor points appear in their place. 868b0b4c70SToby Isaac 878b0b4c70SToby Isaac Level: intermediate 888b0b4c70SToby Isaac 8920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexSetAdjacencyUseAnchors()`, `DMSetAdjacency()`, `DMGetAdjacency()`, `DMPlexDistribute()`, `DMPlexPreallocateOperator()`, `DMPlexSetAnchors()` 908b0b4c70SToby Isaac @*/ 91d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAdjacencyUseAnchors(DM dm, PetscBool *useAnchors) 92d71ae5a4SJacob Faibussowitsch { 938b0b4c70SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data; 948b0b4c70SToby Isaac 958b0b4c70SToby Isaac PetscFunctionBegin; 968b0b4c70SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 974f572ea9SToby Isaac PetscAssertPointer(useAnchors, 2); 985b317d89SToby Isaac *useAnchors = mesh->useAnchors; 993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1008b0b4c70SToby Isaac } 1018b0b4c70SToby Isaac 102d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetAdjacency_Cone_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[]) 103d71ae5a4SJacob Faibussowitsch { 10470034214SMatthew G. Knepley const PetscInt *cone = NULL; 10570034214SMatthew G. Knepley PetscInt numAdj = 0, maxAdjSize = *adjSize, coneSize, c; 10670034214SMatthew G. Knepley 10770034214SMatthew G. Knepley PetscFunctionBeginHot; 1089566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 1099566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 1104b6b44bdSMatthew G. Knepley for (c = 0; c <= coneSize; ++c) { 1114b6b44bdSMatthew G. Knepley const PetscInt point = !c ? p : cone[c - 1]; 11270034214SMatthew G. Knepley const PetscInt *support = NULL; 11370034214SMatthew G. Knepley PetscInt supportSize, s, q; 11470034214SMatthew G. Knepley 1159566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, point, &supportSize)); 1169566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, point, &support)); 11770034214SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 118527e7439SSatish Balay for (q = 0; q < numAdj || ((void)(adj[numAdj++] = support[s]), 0); ++q) { 11970034214SMatthew G. Knepley if (support[s] == adj[q]) break; 12070034214SMatthew G. Knepley } 12163a3b9bcSJacob Faibussowitsch PetscCheck(numAdj <= maxAdjSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%" PetscInt_FMT ")", maxAdjSize); 12270034214SMatthew G. Knepley } 12370034214SMatthew G. Knepley } 12470034214SMatthew G. Knepley *adjSize = numAdj; 1253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12670034214SMatthew G. Knepley } 12770034214SMatthew G. Knepley 128d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetAdjacency_Support_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[]) 129d71ae5a4SJacob Faibussowitsch { 13070034214SMatthew G. Knepley const PetscInt *support = NULL; 13170034214SMatthew G. Knepley PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 13270034214SMatthew G. Knepley 13370034214SMatthew G. Knepley PetscFunctionBeginHot; 1349566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 1359566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 1364b6b44bdSMatthew G. Knepley for (s = 0; s <= supportSize; ++s) { 1374b6b44bdSMatthew G. Knepley const PetscInt point = !s ? p : support[s - 1]; 13870034214SMatthew G. Knepley const PetscInt *cone = NULL; 13970034214SMatthew G. Knepley PetscInt coneSize, c, q; 14070034214SMatthew G. Knepley 1419566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 1429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 14370034214SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 144527e7439SSatish Balay for (q = 0; q < numAdj || ((void)(adj[numAdj++] = cone[c]), 0); ++q) { 14570034214SMatthew G. Knepley if (cone[c] == adj[q]) break; 14670034214SMatthew G. Knepley } 14763a3b9bcSJacob Faibussowitsch PetscCheck(numAdj <= maxAdjSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%" PetscInt_FMT ")", maxAdjSize); 14870034214SMatthew G. Knepley } 14970034214SMatthew G. Knepley } 15070034214SMatthew G. Knepley *adjSize = numAdj; 1513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15270034214SMatthew G. Knepley } 15370034214SMatthew G. Knepley 154d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetAdjacency_Transitive_Internal(DM dm, PetscInt p, PetscBool useClosure, PetscInt *adjSize, PetscInt adj[]) 155d71ae5a4SJacob Faibussowitsch { 15670034214SMatthew G. Knepley PetscInt *star = NULL; 15770034214SMatthew G. Knepley PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 15870034214SMatthew G. Knepley 15970034214SMatthew G. Knepley PetscFunctionBeginHot; 1609566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, &star)); 16170034214SMatthew G. Knepley for (s = 0; s < starSize * 2; s += 2) { 16270034214SMatthew G. Knepley const PetscInt *closure = NULL; 16370034214SMatthew G. Knepley PetscInt closureSize, c, q; 16470034214SMatthew G. Knepley 1659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **)&closure)); 16670034214SMatthew G. Knepley for (c = 0; c < closureSize * 2; c += 2) { 167527e7439SSatish Balay for (q = 0; q < numAdj || ((void)(adj[numAdj++] = closure[c]), 0); ++q) { 16870034214SMatthew G. Knepley if (closure[c] == adj[q]) break; 16970034214SMatthew G. Knepley } 17063a3b9bcSJacob Faibussowitsch PetscCheck(numAdj <= maxAdjSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%" PetscInt_FMT ")", maxAdjSize); 17170034214SMatthew G. Knepley } 1729566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **)&closure)); 17370034214SMatthew G. Knepley } 1749566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, useClosure, &starSize, &star)); 17570034214SMatthew G. Knepley *adjSize = numAdj; 1763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17770034214SMatthew G. Knepley } 17870034214SMatthew G. Knepley 179*16bce5ddSJames Wright // Returns the maximum number of adjancent points in the DMPlex 180*16bce5ddSJames Wright PetscErrorCode DMPlexGetMaxAdjacencySize_Internal(DM dm, PetscBool useAnchors, PetscInt *max_adjacency_size) 181d71ae5a4SJacob Faibussowitsch { 182*16bce5ddSJames Wright PetscInt depth, maxC, maxS, maxP, pStart, pEnd, asiz, maxAnchors = 1; 183*16bce5ddSJames Wright 184*16bce5ddSJames Wright PetscFunctionBeginUser; 185*16bce5ddSJames Wright if (useAnchors) { 1868b0b4c70SToby Isaac PetscSection aSec = NULL; 1878b0b4c70SToby Isaac IS aIS = NULL; 188*16bce5ddSJames Wright PetscInt aStart, aEnd; 1899566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 1908b0b4c70SToby Isaac if (aSec) { 1919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchors)); 19224c766afSToby Isaac maxAnchors = PetscMax(1, maxAnchors); 1939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 1948b0b4c70SToby Isaac } 1958b0b4c70SToby Isaac } 19679bad331SMatthew G. Knepley 1979566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 1989566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 199412e9a14SMatthew G. Knepley depth = PetscMax(depth, -depth); 2009566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxC, &maxS)); 201cf910586SMatthew G. Knepley maxP = maxS * maxC; 202cf910586SMatthew G. Knepley /* Adjacency can be as large as supp(cl(cell)) or cl(supp(vertex)), 203cf910586SMatthew G. Knepley supp(cell) + supp(maxC faces) + supp(maxC^2 edges) + supp(maxC^3 vertices) 204cf910586SMatthew G. Knepley = 0 + maxS*maxC + maxS^2*maxC^2 + maxS^3*maxC^3 205cf910586SMatthew G. Knepley = \sum^d_{i=0} (maxS*maxC)^i - 1 206cf910586SMatthew G. Knepley = (maxS*maxC)^{d+1} - 1 / (maxS*maxC - 1) - 1 207cf910586SMatthew G. Knepley We could improve this by getting the max by strata: 208cf910586SMatthew 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) 209cf910586SMatthew 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] 210cf910586SMatthew G. Knepley and the same with S and C reversed 211cf910586SMatthew G. Knepley */ 212cf910586SMatthew G. Knepley if ((depth == 3 && maxP > 200) || (depth == 2 && maxP > 580)) asiz = pEnd - pStart; 213cf910586SMatthew G. Knepley else asiz = (maxP > 1) ? ((PetscPowInt(maxP, depth + 1) - 1) / (maxP - 1)) : depth + 1; 2148b0b4c70SToby Isaac asiz *= maxAnchors; 215*16bce5ddSJames Wright *max_adjacency_size = PetscMin(asiz, pEnd - pStart); 216*16bce5ddSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 217*16bce5ddSJames Wright } 218*16bce5ddSJames Wright 219*16bce5ddSJames Wright // Returns Adjacent mesh points to the selected point given specific criteria 220*16bce5ddSJames Wright // 221*16bce5ddSJames Wright // + adjSize - Number of adjacent points 222*16bce5ddSJames Wright // - adj - Array of the adjacent points 223*16bce5ddSJames Wright PetscErrorCode DMPlexGetAdjacency_Internal(DM dm, PetscInt p, PetscBool useCone, PetscBool useTransitiveClosure, PetscBool useAnchors, PetscInt *adjSize, PetscInt *adj[]) 224*16bce5ddSJames Wright { 225*16bce5ddSJames Wright static PetscInt asiz = 0; 226*16bce5ddSJames Wright PetscInt aStart = -1, aEnd = -1; 227*16bce5ddSJames Wright PetscInt maxAdjSize; 228*16bce5ddSJames Wright PetscSection aSec = NULL; 229*16bce5ddSJames Wright IS aIS = NULL; 230*16bce5ddSJames Wright const PetscInt *anchors; 231*16bce5ddSJames Wright DM_Plex *mesh = (DM_Plex *)dm->data; 232*16bce5ddSJames Wright 233*16bce5ddSJames Wright PetscFunctionBeginHot; 234*16bce5ddSJames Wright if (useAnchors) { 235*16bce5ddSJames Wright PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 236*16bce5ddSJames Wright if (aSec) { 237*16bce5ddSJames Wright PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 238*16bce5ddSJames Wright PetscCall(ISGetIndices(aIS, &anchors)); 239*16bce5ddSJames Wright } 240*16bce5ddSJames Wright } 241*16bce5ddSJames Wright if (!*adj) { 242*16bce5ddSJames Wright PetscCall(DMPlexGetMaxAdjacencySize_Internal(dm, useAnchors, &asiz)); 2439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(asiz, adj)); 24479bad331SMatthew G. Knepley } 24579bad331SMatthew G. Knepley if (*adjSize < 0) *adjSize = asiz; 2468b0b4c70SToby Isaac maxAdjSize = *adjSize; 2473c1f0c11SLawrence Mitchell if (mesh->useradjacency) { 2489566063dSJacob Faibussowitsch PetscCall((*mesh->useradjacency)(dm, p, adjSize, *adj, mesh->useradjacencyctx)); 2493c1f0c11SLawrence Mitchell } else if (useTransitiveClosure) { 2509566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Transitive_Internal(dm, p, useCone, adjSize, *adj)); 25170034214SMatthew G. Knepley } else if (useCone) { 2529566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Cone_Internal(dm, p, adjSize, *adj)); 25370034214SMatthew G. Knepley } else { 2549566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Support_Internal(dm, p, adjSize, *adj)); 25570034214SMatthew G. Knepley } 2565b317d89SToby Isaac if (useAnchors && aSec) { 2578b0b4c70SToby Isaac PetscInt origSize = *adjSize; 2588b0b4c70SToby Isaac PetscInt numAdj = origSize; 2598b0b4c70SToby Isaac PetscInt i = 0, j; 2608b0b4c70SToby Isaac PetscInt *orig = *adj; 2618b0b4c70SToby Isaac 2628b0b4c70SToby Isaac while (i < origSize) { 2638b0b4c70SToby Isaac PetscInt p = orig[i]; 2648b0b4c70SToby Isaac PetscInt aDof = 0; 2658b0b4c70SToby Isaac 26648a46eb9SPierre Jolivet if (p >= aStart && p < aEnd) PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 2678b0b4c70SToby Isaac if (aDof) { 2688b0b4c70SToby Isaac PetscInt aOff; 2698b0b4c70SToby Isaac PetscInt s, q; 2708b0b4c70SToby Isaac 271ad540459SPierre Jolivet for (j = i + 1; j < numAdj; j++) orig[j - 1] = orig[j]; 2728b0b4c70SToby Isaac origSize--; 2738b0b4c70SToby Isaac numAdj--; 2749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 2758b0b4c70SToby Isaac for (s = 0; s < aDof; ++s) { 276527e7439SSatish Balay for (q = 0; q < numAdj || ((void)(orig[numAdj++] = anchors[aOff + s]), 0); ++q) { 2778b0b4c70SToby Isaac if (anchors[aOff + s] == orig[q]) break; 2788b0b4c70SToby Isaac } 27963a3b9bcSJacob Faibussowitsch PetscCheck(numAdj <= maxAdjSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%" PetscInt_FMT ")", maxAdjSize); 2808b0b4c70SToby Isaac } 2819371c9d4SSatish Balay } else { 2828b0b4c70SToby Isaac i++; 2838b0b4c70SToby Isaac } 2848b0b4c70SToby Isaac } 2858b0b4c70SToby Isaac *adjSize = numAdj; 2869566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 2878b0b4c70SToby Isaac } 2883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28970034214SMatthew G. Knepley } 29070034214SMatthew G. Knepley 29170034214SMatthew G. Knepley /*@ 29270034214SMatthew G. Knepley DMPlexGetAdjacency - Return all points adjacent to the given point 29370034214SMatthew G. Knepley 29470034214SMatthew G. Knepley Input Parameters: 29520f4b53cSBarry Smith + dm - The `DM` object 2966b867d5aSJose E. Roman - p - The point 29770034214SMatthew G. Knepley 2986b867d5aSJose E. Roman Input/Output Parameters: 29920f4b53cSBarry Smith + adjSize - The maximum size of `adj` if it is non-`NULL`, or `PETSC_DETERMINE`; 3006b867d5aSJose E. Roman on output the number of adjacent points 30120f4b53cSBarry Smith - adj - Either `NULL` so that the array is allocated, or an existing array with size `adjSize`; 3026b867d5aSJose E. Roman on output contains the adjacent points 30370034214SMatthew G. Knepley 30470034214SMatthew G. Knepley Level: advanced 30570034214SMatthew G. Knepley 30695452b02SPatrick Sanan Notes: 30720f4b53cSBarry Smith The user must `PetscFree()` the `adj` array if it was not passed in. 30870034214SMatthew G. Knepley 30920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMCreateMatrix()`, `DMPlexPreallocateOperator()` 31070034214SMatthew G. Knepley @*/ 311d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAdjacency(DM dm, PetscInt p, PetscInt *adjSize, PetscInt *adj[]) 312d71ae5a4SJacob Faibussowitsch { 3131cf84007SMatthew G. Knepley PetscBool useCone, useClosure, useAnchors; 31470034214SMatthew G. Knepley 31570034214SMatthew G. Knepley PetscFunctionBeginHot; 31670034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3174f572ea9SToby Isaac PetscAssertPointer(adjSize, 3); 3184f572ea9SToby Isaac PetscAssertPointer(adj, 4); 3199566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 3209566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors)); 3219566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, adjSize, adj)); 3223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32370034214SMatthew G. Knepley } 32408633170SToby Isaac 325b0a623aaSMatthew G. Knepley /*@ 32620f4b53cSBarry Smith DMPlexCreateTwoSidedProcessSF - Create an `PetscSF` which just has process connectivity 327b0a623aaSMatthew G. Knepley 32820f4b53cSBarry Smith Collective 329b0a623aaSMatthew G. Knepley 330b0a623aaSMatthew G. Knepley Input Parameters: 33120f4b53cSBarry Smith + dm - The `DM` 33220f4b53cSBarry Smith . sfPoint - The `PetscSF` which encodes point connectivity 33320f4b53cSBarry Smith . rootRankSection - to be documented 33420f4b53cSBarry Smith . rootRanks - to be documented 33560225df5SJacob Faibussowitsch . leafRankSection - to be documented 33620f4b53cSBarry Smith - leafRanks - to be documented 337b0a623aaSMatthew G. Knepley 338b0a623aaSMatthew G. Knepley Output Parameters: 33920f4b53cSBarry Smith + processRanks - A list of process neighbors, or `NULL` 34020f4b53cSBarry Smith - sfProcess - An `PetscSF` encoding the two-sided process connectivity, or `NULL` 341b0a623aaSMatthew G. Knepley 342b0a623aaSMatthew G. Knepley Level: developer 343b0a623aaSMatthew G. Knepley 34420f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSFCreate()`, `DMPlexCreateProcessSF()` 345b0a623aaSMatthew G. Knepley @*/ 346ce78bad3SBarry Smith PetscErrorCode DMPlexCreateTwoSidedProcessSF(DM dm, PetscSF sfPoint, PetscSection rootRankSection, IS rootRanks, PetscSection leafRankSection, IS leafRanks, PeOp IS *processRanks, PeOp PetscSF *sfProcess) 347d71ae5a4SJacob Faibussowitsch { 348b0a623aaSMatthew G. Knepley const PetscSFNode *remotePoints; 349b0a623aaSMatthew G. Knepley PetscInt *localPointsNew; 350b0a623aaSMatthew G. Knepley PetscSFNode *remotePointsNew; 351b0a623aaSMatthew G. Knepley const PetscInt *nranks; 352b0a623aaSMatthew G. Knepley PetscInt *ranksNew; 353b0a623aaSMatthew G. Knepley PetscBT neighbors; 354b0a623aaSMatthew G. Knepley PetscInt pStart, pEnd, p, numLeaves, l, numNeighbors, n; 3559852e123SBarry Smith PetscMPIInt size, proc, rank; 356b0a623aaSMatthew G. Knepley 357b0a623aaSMatthew G. Knepley PetscFunctionBegin; 358b0a623aaSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 359b0a623aaSMatthew G. Knepley PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2); 3604f572ea9SToby Isaac if (processRanks) PetscAssertPointer(processRanks, 7); 3614f572ea9SToby Isaac if (sfProcess) PetscAssertPointer(sfProcess, 8); 3629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 3639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 3649566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &numLeaves, NULL, &remotePoints)); 3659566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(size, &neighbors)); 3669566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(size, neighbors)); 367b0a623aaSMatthew G. Knepley /* Compute root-to-leaf process connectivity */ 3689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(rootRankSection, &pStart, &pEnd)); 3699566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rootRanks, &nranks)); 370b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 371b0a623aaSMatthew G. Knepley PetscInt ndof, noff, n; 372b0a623aaSMatthew G. Knepley 3739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootRankSection, p, &ndof)); 3749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootRankSection, p, &noff)); 3759566063dSJacob Faibussowitsch for (n = 0; n < ndof; ++n) PetscCall(PetscBTSet(neighbors, nranks[noff + n])); 376b0a623aaSMatthew G. Knepley } 3779566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rootRanks, &nranks)); 378b0a623aaSMatthew G. Knepley /* Compute leaf-to-neighbor process connectivity */ 3799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafRankSection, &pStart, &pEnd)); 3809566063dSJacob Faibussowitsch PetscCall(ISGetIndices(leafRanks, &nranks)); 381b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 382b0a623aaSMatthew G. Knepley PetscInt ndof, noff, n; 383b0a623aaSMatthew G. Knepley 3849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafRankSection, p, &ndof)); 3859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafRankSection, p, &noff)); 3869566063dSJacob Faibussowitsch for (n = 0; n < ndof; ++n) PetscCall(PetscBTSet(neighbors, nranks[noff + n])); 387b0a623aaSMatthew G. Knepley } 3889566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(leafRanks, &nranks)); 389b0a623aaSMatthew G. Knepley /* Compute leaf-to-root process connectivity */ 3903ba16761SJacob Faibussowitsch for (l = 0; l < numLeaves; ++l) PetscCall(PetscBTSet(neighbors, remotePoints[l].rank)); 391b0a623aaSMatthew G. Knepley /* Calculate edges */ 3923ba16761SJacob Faibussowitsch PetscCall(PetscBTClear(neighbors, rank)); 3939371c9d4SSatish Balay for (proc = 0, numNeighbors = 0; proc < size; ++proc) { 3949371c9d4SSatish Balay if (PetscBTLookup(neighbors, proc)) ++numNeighbors; 3959371c9d4SSatish Balay } 3969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNeighbors, &ranksNew)); 3979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNeighbors, &localPointsNew)); 3989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNeighbors, &remotePointsNew)); 3999852e123SBarry Smith for (proc = 0, n = 0; proc < size; ++proc) { 400b0a623aaSMatthew G. Knepley if (PetscBTLookup(neighbors, proc)) { 401b0a623aaSMatthew G. Knepley ranksNew[n] = proc; 402b0a623aaSMatthew G. Knepley localPointsNew[n] = proc; 403b0a623aaSMatthew G. Knepley remotePointsNew[n].index = rank; 404b0a623aaSMatthew G. Knepley remotePointsNew[n].rank = proc; 405b0a623aaSMatthew G. Knepley ++n; 406b0a623aaSMatthew G. Knepley } 407b0a623aaSMatthew G. Knepley } 4089566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&neighbors)); 4099566063dSJacob Faibussowitsch if (processRanks) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), numNeighbors, ranksNew, PETSC_OWN_POINTER, processRanks)); 4109566063dSJacob Faibussowitsch else PetscCall(PetscFree(ranksNew)); 411b0a623aaSMatthew G. Knepley if (sfProcess) { 4129566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess)); 4139566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*sfProcess, "Two-Sided Process SF")); 4149566063dSJacob Faibussowitsch PetscCall(PetscSFSetFromOptions(*sfProcess)); 4159566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sfProcess, size, numNeighbors, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER)); 416b0a623aaSMatthew G. Knepley } 4173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 418b0a623aaSMatthew G. Knepley } 419b0a623aaSMatthew G. Knepley 420b0a623aaSMatthew G. Knepley /*@ 421b0a623aaSMatthew G. Knepley DMPlexDistributeOwnership - Compute owner information for shared points. This basically gets two-sided for an SF. 422b0a623aaSMatthew G. Knepley 42320f4b53cSBarry Smith Collective 424b0a623aaSMatthew G. Knepley 425b0a623aaSMatthew G. Knepley Input Parameter: 42620f4b53cSBarry Smith . dm - The `DM` 427b0a623aaSMatthew G. Knepley 428b0a623aaSMatthew G. Knepley Output Parameters: 429b0a623aaSMatthew G. Knepley + rootSection - The number of leaves for a given root point 430b0a623aaSMatthew G. Knepley . rootrank - The rank of each edge into the root point 431b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point 432b0a623aaSMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point 433b0a623aaSMatthew G. Knepley 434b0a623aaSMatthew G. Knepley Level: developer 435b0a623aaSMatthew G. Knepley 43620f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabel()`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 437b0a623aaSMatthew G. Knepley @*/ 438d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeOwnership(DM dm, PetscSection rootSection, IS *rootrank, PetscSection leafSection, IS *leafrank) 439d71ae5a4SJacob Faibussowitsch { 440b0a623aaSMatthew G. Knepley MPI_Comm comm; 441b0a623aaSMatthew G. Knepley PetscSF sfPoint; 442b0a623aaSMatthew G. Knepley const PetscInt *rootdegree; 443b0a623aaSMatthew G. Knepley PetscInt *myrank, *remoterank; 444b0a623aaSMatthew G. Knepley PetscInt pStart, pEnd, p, nedges; 445b0a623aaSMatthew G. Knepley PetscMPIInt rank; 446b0a623aaSMatthew G. Knepley 447b0a623aaSMatthew G. Knepley PetscFunctionBegin; 4489566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 4509566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4519566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 452b0a623aaSMatthew G. Knepley /* Compute number of leaves for each root */ 4539566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rootSection, "Root Section")); 4549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection, pStart, pEnd)); 4559566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sfPoint, &rootdegree)); 4569566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sfPoint, &rootdegree)); 4579566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(rootSection, p, rootdegree[p - pStart])); 4589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection)); 459b0a623aaSMatthew G. Knepley /* Gather rank of each leaf to root */ 4609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &nedges)); 4619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &myrank)); 4629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nedges, &remoterank)); 463b0a623aaSMatthew G. Knepley for (p = 0; p < pEnd - pStart; ++p) myrank[p] = rank; 4649566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sfPoint, MPIU_INT, myrank, remoterank)); 4659566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sfPoint, MPIU_INT, myrank, remoterank)); 4669566063dSJacob Faibussowitsch PetscCall(PetscFree(myrank)); 4679566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, nedges, remoterank, PETSC_OWN_POINTER, rootrank)); 468b0a623aaSMatthew G. Knepley /* Distribute remote ranks to leaves */ 4699566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)leafSection, "Leaf Section")); 4709566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeFieldIS(dm, sfPoint, rootSection, *rootrank, leafSection, leafrank)); 4713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 472b0a623aaSMatthew G. Knepley } 473b0a623aaSMatthew G. Knepley 474ce78bad3SBarry Smith /*@ 475c506a872SMatthew G. Knepley DMPlexCreateOverlapLabel - Compute a label indicating what overlap points should be sent to new processes 476b0a623aaSMatthew G. Knepley 47720f4b53cSBarry Smith Collective 478b0a623aaSMatthew G. Knepley 479b0a623aaSMatthew G. Knepley Input Parameters: 48020f4b53cSBarry Smith + dm - The `DM` 48124d039d7SMichael Lange . levels - Number of overlap levels 482b0a623aaSMatthew G. Knepley . rootSection - The number of leaves for a given root point 483b0a623aaSMatthew G. Knepley . rootrank - The rank of each edge into the root point 484b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point 485b0a623aaSMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point 486b0a623aaSMatthew G. Knepley 487064ec1f3Sprj- Output Parameter: 48820f4b53cSBarry Smith . ovLabel - `DMLabel` containing remote overlap contributions as point/rank pairings 489b0a623aaSMatthew G. Knepley 490b0a623aaSMatthew G. Knepley Level: developer 491b0a623aaSMatthew G. Knepley 49220f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabelFromLabels()`, `DMPlexGetAdjacency()`, `DMPlexDistributeOwnership()`, `DMPlexDistribute()` 493b0a623aaSMatthew G. Knepley @*/ 494d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateOverlapLabel(DM dm, PetscInt levels, PetscSection rootSection, IS rootrank, PetscSection leafSection, IS leafrank, DMLabel *ovLabel) 495d71ae5a4SJacob Faibussowitsch { 496e540f424SMichael Lange MPI_Comm comm; 497b0a623aaSMatthew G. Knepley DMLabel ovAdjByRank; /* A DMLabel containing all points adjacent to shared points, separated by rank (value in label) */ 498874ddda9SLisandro Dalcin PetscSF sfPoint; 499b0a623aaSMatthew G. Knepley const PetscSFNode *remote; 500b0a623aaSMatthew G. Knepley const PetscInt *local; 5011fd9873aSMichael Lange const PetscInt *nrank, *rrank; 502b0a623aaSMatthew G. Knepley PetscInt *adj = NULL; 5031fd9873aSMichael Lange PetscInt pStart, pEnd, p, sStart, sEnd, nleaves, l; 5049852e123SBarry Smith PetscMPIInt rank, size; 50531bc6364SLisandro Dalcin PetscBool flg; 506b0a623aaSMatthew G. Knepley 507b0a623aaSMatthew G. Knepley PetscFunctionBegin; 5086ba1a4c7SVaclav Hapla *ovLabel = NULL; 5099566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 5109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 5119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 5123ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 5139566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 5149566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 515d1674c6dSMatthew Knepley if (!levels) { 516d1674c6dSMatthew Knepley /* Add owned points */ 5179566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel)); 5189566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) PetscCall(DMLabelSetValue(*ovLabel, p, rank)); 5193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 520d1674c6dSMatthew Knepley } 5219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafSection, &sStart, &sEnd)); 5229566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote)); 5239566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap adjacency", &ovAdjByRank)); 524b0a623aaSMatthew G. Knepley /* Handle leaves: shared with the root point */ 525b0a623aaSMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 526b0a623aaSMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a; 527b0a623aaSMatthew G. Knepley 5289566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, local ? local[l] : l, &adjSize, &adj)); 5299566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remote[l].rank)); 530b0a623aaSMatthew G. Knepley } 5319566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rootrank, &rrank)); 5329566063dSJacob Faibussowitsch PetscCall(ISGetIndices(leafrank, &nrank)); 533b0a623aaSMatthew G. Knepley /* Handle roots */ 534b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 535b0a623aaSMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, neighbors = 0, noff, n, a; 536b0a623aaSMatthew G. Knepley 537b0a623aaSMatthew G. Knepley if ((p >= sStart) && (p < sEnd)) { 538b0a623aaSMatthew G. Knepley /* Some leaves share a root with other leaves on different processes */ 5399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, p, &neighbors)); 540b0a623aaSMatthew G. Knepley if (neighbors) { 5419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafSection, p, &noff)); 5429566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 543b0a623aaSMatthew G. Knepley for (n = 0; n < neighbors; ++n) { 544b0a623aaSMatthew G. Knepley const PetscInt remoteRank = nrank[noff + n]; 545b0a623aaSMatthew G. Knepley 546b0a623aaSMatthew G. Knepley if (remoteRank == rank) continue; 5479566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 548b0a623aaSMatthew G. Knepley } 549b0a623aaSMatthew G. Knepley } 550b0a623aaSMatthew G. Knepley } 551b0a623aaSMatthew G. Knepley /* Roots are shared with leaves */ 5529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSection, p, &neighbors)); 553b0a623aaSMatthew G. Knepley if (!neighbors) continue; 5549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, p, &noff)); 5559566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 556b0a623aaSMatthew G. Knepley for (n = 0; n < neighbors; ++n) { 557b0a623aaSMatthew G. Knepley const PetscInt remoteRank = rrank[noff + n]; 558b0a623aaSMatthew G. Knepley 559b0a623aaSMatthew G. Knepley if (remoteRank == rank) continue; 5609566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 561b0a623aaSMatthew G. Knepley } 562b0a623aaSMatthew G. Knepley } 5639566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 5649566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rootrank, &rrank)); 5659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(leafrank, &nrank)); 56624d039d7SMichael Lange /* Add additional overlap levels */ 567be200f8dSMichael Lange for (l = 1; l < levels; l++) { 568be200f8dSMichael Lange /* Propagate point donations over SF to capture remote connections */ 5699566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelPropagate(dm, ovAdjByRank)); 570be200f8dSMichael Lange /* Add next level of point donations to the label */ 5719566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelAdjacency(dm, ovAdjByRank)); 572be200f8dSMichael Lange } 57326a7d390SMatthew G. Knepley /* We require the closure in the overlap */ 5749566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelClosure(dm, ovAdjByRank)); 5759566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-overlap_view", &flg)); 576e540f424SMichael Lange if (flg) { 577825f8a23SLisandro Dalcin PetscViewer viewer; 5789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &viewer)); 5799566063dSJacob Faibussowitsch PetscCall(DMLabelView(ovAdjByRank, viewer)); 580b0a623aaSMatthew G. Knepley } 581874ddda9SLisandro Dalcin /* Invert sender to receiver label */ 5829566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel)); 5839566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelInvert(dm, ovAdjByRank, NULL, *ovLabel)); 584a9f1d5b2SMichael Lange /* Add owned points, except for shared local points */ 5859566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) PetscCall(DMLabelSetValue(*ovLabel, p, rank)); 586e540f424SMichael Lange for (l = 0; l < nleaves; ++l) { 5879566063dSJacob Faibussowitsch PetscCall(DMLabelClearValue(*ovLabel, local[l], rank)); 5889566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(*ovLabel, remote[l].index, remote[l].rank)); 589e540f424SMichael Lange } 590e540f424SMichael Lange /* Clean up */ 5919566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&ovAdjByRank)); 5923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 593b0a623aaSMatthew G. Knepley } 59470034214SMatthew G. Knepley 595d71ae5a4SJacob Faibussowitsch static PetscErrorCode HandlePoint_Private(DM dm, PetscInt p, PetscSection section, const PetscInt ranks[], PetscInt numExLabels, const DMLabel exLabel[], const PetscInt exValue[], DMLabel ovAdjByRank) 596d71ae5a4SJacob Faibussowitsch { 597c506a872SMatthew G. Knepley PetscInt neighbors, el; 598c506a872SMatthew G. Knepley 599c506a872SMatthew G. Knepley PetscFunctionBegin; 600c506a872SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, p, &neighbors)); 601c506a872SMatthew G. Knepley if (neighbors) { 602c506a872SMatthew G. Knepley PetscInt *adj = NULL; 603c506a872SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, noff, n, a; 604c506a872SMatthew G. Knepley PetscMPIInt rank; 605c506a872SMatthew G. Knepley 606c506a872SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 607c506a872SMatthew G. Knepley PetscCall(PetscSectionGetOffset(section, p, &noff)); 608c506a872SMatthew G. Knepley PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 609c506a872SMatthew G. Knepley for (n = 0; n < neighbors; ++n) { 610c506a872SMatthew G. Knepley const PetscInt remoteRank = ranks[noff + n]; 611c506a872SMatthew G. Knepley 612c506a872SMatthew G. Knepley if (remoteRank == rank) continue; 613c506a872SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 614c506a872SMatthew G. Knepley PetscBool insert = PETSC_TRUE; 615c506a872SMatthew G. Knepley 616c506a872SMatthew G. Knepley for (el = 0; el < numExLabels; ++el) { 617c506a872SMatthew G. Knepley PetscInt exVal; 618c506a872SMatthew G. Knepley PetscCall(DMLabelGetValue(exLabel[el], adj[a], &exVal)); 6199371c9d4SSatish Balay if (exVal == exValue[el]) { 6209371c9d4SSatish Balay insert = PETSC_FALSE; 6219371c9d4SSatish Balay break; 6229371c9d4SSatish Balay } 623c506a872SMatthew G. Knepley } 624c506a872SMatthew G. Knepley if (insert) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 625c506a872SMatthew G. Knepley } 626c506a872SMatthew G. Knepley } 627f88a03deSMatthew G. Knepley PetscCall(PetscFree(adj)); 628c506a872SMatthew G. Knepley } 6293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 630c506a872SMatthew G. Knepley } 631c506a872SMatthew G. Knepley 632c506a872SMatthew G. Knepley /*@C 633c506a872SMatthew G. Knepley DMPlexCreateOverlapLabelFromLabels - Compute a label indicating what overlap points should be sent to new processes 634c506a872SMatthew G. Knepley 63520f4b53cSBarry Smith Collective 636c506a872SMatthew G. Knepley 637c506a872SMatthew G. Knepley Input Parameters: 63820f4b53cSBarry Smith + dm - The `DM` 639c506a872SMatthew G. Knepley . numLabels - The number of labels to draw candidate points from 640c506a872SMatthew G. Knepley . label - An array of labels containing candidate points 641c506a872SMatthew G. Knepley . value - An array of label values marking the candidate points 642c506a872SMatthew G. Knepley . numExLabels - The number of labels to use for exclusion 64320f4b53cSBarry Smith . exLabel - An array of labels indicating points to be excluded, or `NULL` 64420f4b53cSBarry Smith . exValue - An array of label values to be excluded, or `NULL` 645c506a872SMatthew G. Knepley . rootSection - The number of leaves for a given root point 646c506a872SMatthew G. Knepley . rootrank - The rank of each edge into the root point 647c506a872SMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point 648c506a872SMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point 649c506a872SMatthew G. Knepley 650c506a872SMatthew G. Knepley Output Parameter: 65120f4b53cSBarry Smith . ovLabel - `DMLabel` containing remote overlap contributions as point/rank pairings 65220f4b53cSBarry Smith 65320f4b53cSBarry Smith Level: developer 654c506a872SMatthew G. Knepley 655c506a872SMatthew G. Knepley Note: 656c506a872SMatthew G. Knepley The candidate points are only added to the overlap if they are adjacent to a shared point 657c506a872SMatthew G. Knepley 65820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabel()`, `DMPlexGetAdjacency()`, `DMPlexDistributeOwnership()`, `DMPlexDistribute()` 659c506a872SMatthew G. Knepley @*/ 660d71ae5a4SJacob 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) 661d71ae5a4SJacob Faibussowitsch { 662c506a872SMatthew G. Knepley MPI_Comm comm; 663c506a872SMatthew G. Knepley DMLabel ovAdjByRank; /* A DMLabel containing all points adjacent to shared points, separated by rank (value in label) */ 664c506a872SMatthew G. Knepley PetscSF sfPoint; 665c506a872SMatthew G. Knepley const PetscSFNode *remote; 666c506a872SMatthew G. Knepley const PetscInt *local; 667c506a872SMatthew G. Knepley const PetscInt *nrank, *rrank; 668c506a872SMatthew G. Knepley PetscInt *adj = NULL; 669c506a872SMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, nleaves, l, el; 670c506a872SMatthew G. Knepley PetscMPIInt rank, size; 671c506a872SMatthew G. Knepley PetscBool flg; 672c506a872SMatthew G. Knepley 673c506a872SMatthew G. Knepley PetscFunctionBegin; 674c506a872SMatthew G. Knepley *ovLabel = NULL; 675c506a872SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 676c506a872SMatthew G. Knepley PetscCallMPI(MPI_Comm_size(comm, &size)); 677c506a872SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 6783ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 679c506a872SMatthew G. Knepley PetscCall(DMGetPointSF(dm, &sfPoint)); 680c506a872SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 681c506a872SMatthew G. Knepley PetscCall(PetscSectionGetChart(leafSection, &sStart, &sEnd)); 682c506a872SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote)); 683c506a872SMatthew G. Knepley PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap adjacency", &ovAdjByRank)); 684c506a872SMatthew G. Knepley PetscCall(ISGetIndices(rootrank, &rrank)); 685c506a872SMatthew G. Knepley PetscCall(ISGetIndices(leafrank, &nrank)); 686c506a872SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 687c506a872SMatthew G. Knepley IS valIS; 688c506a872SMatthew G. Knepley const PetscInt *points; 689c506a872SMatthew G. Knepley PetscInt n; 690c506a872SMatthew G. Knepley 691c506a872SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label[l], value[l], &valIS)); 692c506a872SMatthew G. Knepley if (!valIS) continue; 693c506a872SMatthew G. Knepley PetscCall(ISGetIndices(valIS, &points)); 694c506a872SMatthew G. Knepley PetscCall(ISGetLocalSize(valIS, &n)); 695c506a872SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) { 696c506a872SMatthew G. Knepley const PetscInt p = points[i]; 697c506a872SMatthew G. Knepley 698c506a872SMatthew G. Knepley if ((p >= sStart) && (p < sEnd)) { 699c506a872SMatthew G. Knepley PetscInt loc, adjSize = PETSC_DETERMINE; 700c506a872SMatthew G. Knepley 701c506a872SMatthew G. Knepley /* Handle leaves: shared with the root point */ 702c506a872SMatthew G. Knepley if (local) PetscCall(PetscFindInt(p, nleaves, local, &loc)); 703c506a872SMatthew G. Knepley else loc = (p >= 0 && p < nleaves) ? p : -1; 704c506a872SMatthew G. Knepley if (loc >= 0) { 705c506a872SMatthew G. Knepley const PetscInt remoteRank = remote[loc].rank; 706c506a872SMatthew G. Knepley 707c506a872SMatthew G. Knepley PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 708c506a872SMatthew G. Knepley for (PetscInt a = 0; a < adjSize; ++a) { 709c506a872SMatthew G. Knepley PetscBool insert = PETSC_TRUE; 710c506a872SMatthew G. Knepley 711c506a872SMatthew G. Knepley for (el = 0; el < numExLabels; ++el) { 712c506a872SMatthew G. Knepley PetscInt exVal; 713c506a872SMatthew G. Knepley PetscCall(DMLabelGetValue(exLabel[el], adj[a], &exVal)); 7149371c9d4SSatish Balay if (exVal == exValue[el]) { 7159371c9d4SSatish Balay insert = PETSC_FALSE; 7169371c9d4SSatish Balay break; 7179371c9d4SSatish Balay } 718c506a872SMatthew G. Knepley } 719c506a872SMatthew G. Knepley if (insert) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 720c506a872SMatthew G. Knepley } 721c506a872SMatthew G. Knepley } 722c506a872SMatthew G. Knepley /* Some leaves share a root with other leaves on different processes */ 7233ba16761SJacob Faibussowitsch PetscCall(HandlePoint_Private(dm, p, leafSection, nrank, numExLabels, exLabel, exValue, ovAdjByRank)); 724c506a872SMatthew G. Knepley } 725c506a872SMatthew G. Knepley /* Roots are shared with leaves */ 7263ba16761SJacob Faibussowitsch PetscCall(HandlePoint_Private(dm, p, rootSection, rrank, numExLabels, exLabel, exValue, ovAdjByRank)); 727c506a872SMatthew G. Knepley } 728c506a872SMatthew G. Knepley PetscCall(ISRestoreIndices(valIS, &points)); 729c506a872SMatthew G. Knepley PetscCall(ISDestroy(&valIS)); 730c506a872SMatthew G. Knepley } 731c506a872SMatthew G. Knepley PetscCall(PetscFree(adj)); 732c506a872SMatthew G. Knepley PetscCall(ISRestoreIndices(rootrank, &rrank)); 733c506a872SMatthew G. Knepley PetscCall(ISRestoreIndices(leafrank, &nrank)); 734c506a872SMatthew G. Knepley /* We require the closure in the overlap */ 735c506a872SMatthew G. Knepley PetscCall(DMPlexPartitionLabelClosure(dm, ovAdjByRank)); 736c506a872SMatthew G. Knepley PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-overlap_view", &flg)); 737c506a872SMatthew G. Knepley if (flg) { 738c506a872SMatthew G. Knepley PetscViewer viewer; 739c506a872SMatthew G. Knepley PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &viewer)); 740c506a872SMatthew G. Knepley PetscCall(DMLabelView(ovAdjByRank, viewer)); 741c506a872SMatthew G. Knepley } 742c506a872SMatthew G. Knepley /* Invert sender to receiver label */ 743c506a872SMatthew G. Knepley PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel)); 744c506a872SMatthew G. Knepley PetscCall(DMPlexPartitionLabelInvert(dm, ovAdjByRank, NULL, *ovLabel)); 745c506a872SMatthew G. Knepley /* Add owned points, except for shared local points */ 746c506a872SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) PetscCall(DMLabelSetValue(*ovLabel, p, rank)); 747c506a872SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 748c506a872SMatthew G. Knepley PetscCall(DMLabelClearValue(*ovLabel, local[l], rank)); 749c506a872SMatthew G. Knepley PetscCall(DMLabelSetValue(*ovLabel, remote[l].index, remote[l].rank)); 750c506a872SMatthew G. Knepley } 751c506a872SMatthew G. Knepley /* Clean up */ 752c506a872SMatthew G. Knepley PetscCall(DMLabelDestroy(&ovAdjByRank)); 7533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 754c506a872SMatthew G. Knepley } 755c506a872SMatthew G. Knepley 756cc4c1da9SBarry Smith /*@ 75720f4b53cSBarry Smith DMPlexCreateOverlapMigrationSF - Create a `PetscSF` describing the new mesh distribution to make the overlap described by the input `PetscSF` 75824cc2ca5SMatthew G. Knepley 75920f4b53cSBarry Smith Collective 76024cc2ca5SMatthew G. Knepley 76124cc2ca5SMatthew G. Knepley Input Parameters: 76220f4b53cSBarry Smith + dm - The `DM` 76320f4b53cSBarry Smith - overlapSF - The `PetscSF` mapping ghost points in overlap to owner points on other processes 76424cc2ca5SMatthew G. Knepley 765064ec1f3Sprj- Output Parameter: 76620f4b53cSBarry Smith . migrationSF - A `PetscSF` that maps original points in old locations to points in new locations 76724cc2ca5SMatthew G. Knepley 76824cc2ca5SMatthew G. Knepley Level: developer 76924cc2ca5SMatthew G. Knepley 77020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabel()`, `DMPlexDistributeOverlap()`, `DMPlexDistribute()` 77124cc2ca5SMatthew G. Knepley @*/ 772d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateOverlapMigrationSF(DM dm, PetscSF overlapSF, PetscSF *migrationSF) 773d71ae5a4SJacob Faibussowitsch { 77446f9b1c3SMichael Lange MPI_Comm comm; 7759852e123SBarry Smith PetscMPIInt rank, size; 77646f9b1c3SMichael Lange PetscInt d, dim, p, pStart, pEnd, nroots, nleaves, newLeaves, point, numSharedPoints; 77746f9b1c3SMichael Lange PetscInt *pointDepths, *remoteDepths, *ilocal; 77846f9b1c3SMichael Lange PetscInt *depthRecv, *depthShift, *depthIdx; 77946f9b1c3SMichael Lange PetscSFNode *iremote; 78046f9b1c3SMichael Lange PetscSF pointSF; 78146f9b1c3SMichael Lange const PetscInt *sharedLocal; 78246f9b1c3SMichael Lange const PetscSFNode *overlapRemote, *sharedRemote; 78346f9b1c3SMichael Lange 78446f9b1c3SMichael Lange PetscFunctionBegin; 78546f9b1c3SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7869566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 7879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 7899566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 79046f9b1c3SMichael Lange 79146f9b1c3SMichael Lange /* Before building the migration SF we need to know the new stratum offsets */ 7929566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(overlapSF, &nroots, &nleaves, NULL, &overlapRemote)); 7939566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths)); 79446f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) { 7959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 79646f9b1c3SMichael Lange for (p = pStart; p < pEnd; p++) pointDepths[p] = d; 79746f9b1c3SMichael Lange } 79846f9b1c3SMichael Lange for (p = 0; p < nleaves; p++) remoteDepths[p] = -1; 7999566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(overlapSF, MPIU_INT, pointDepths, remoteDepths, MPI_REPLACE)); 8009566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(overlapSF, MPIU_INT, pointDepths, remoteDepths, MPI_REPLACE)); 80146f9b1c3SMichael Lange 8022d4ee042Sprj- /* Count received points in each stratum and compute the internal strata shift */ 8039566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim + 1, &depthRecv, dim + 1, &depthShift, dim + 1, &depthIdx)); 80446f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) depthRecv[d] = 0; 80546f9b1c3SMichael Lange for (p = 0; p < nleaves; p++) depthRecv[remoteDepths[p]]++; 80646f9b1c3SMichael Lange depthShift[dim] = 0; 80746f9b1c3SMichael Lange for (d = 0; d < dim; d++) depthShift[d] = depthRecv[dim]; 80846f9b1c3SMichael Lange for (d = 1; d < dim; d++) depthShift[d] += depthRecv[0]; 80946f9b1c3SMichael Lange for (d = dim - 2; d > 0; d--) depthShift[d] += depthRecv[d + 1]; 81046f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) { 8119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 81246f9b1c3SMichael Lange depthIdx[d] = pStart + depthShift[d]; 81346f9b1c3SMichael Lange } 81446f9b1c3SMichael Lange 81546f9b1c3SMichael Lange /* Form the overlap SF build an SF that describes the full overlap migration SF */ 8169566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 81746f9b1c3SMichael Lange newLeaves = pEnd - pStart + nleaves; 8189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newLeaves, &ilocal)); 8199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newLeaves, &iremote)); 82046f9b1c3SMichael Lange /* First map local points to themselves */ 82146f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) { 8229566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 82346f9b1c3SMichael Lange for (p = pStart; p < pEnd; p++) { 82446f9b1c3SMichael Lange point = p + depthShift[d]; 82546f9b1c3SMichael Lange ilocal[point] = point; 82646f9b1c3SMichael Lange iremote[point].index = p; 82746f9b1c3SMichael Lange iremote[point].rank = rank; 82846f9b1c3SMichael Lange depthIdx[d]++; 82946f9b1c3SMichael Lange } 83046f9b1c3SMichael Lange } 83146f9b1c3SMichael Lange 83246f9b1c3SMichael Lange /* Add in the remote roots for currently shared points */ 8339566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &pointSF)); 8349566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, NULL, &numSharedPoints, &sharedLocal, &sharedRemote)); 83546f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) { 8369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 83746f9b1c3SMichael Lange for (p = 0; p < numSharedPoints; p++) { 83846f9b1c3SMichael Lange if (pStart <= sharedLocal[p] && sharedLocal[p] < pEnd) { 83946f9b1c3SMichael Lange point = sharedLocal[p] + depthShift[d]; 84046f9b1c3SMichael Lange iremote[point].index = sharedRemote[p].index; 84146f9b1c3SMichael Lange iremote[point].rank = sharedRemote[p].rank; 84246f9b1c3SMichael Lange } 84346f9b1c3SMichael Lange } 84446f9b1c3SMichael Lange } 84546f9b1c3SMichael Lange 84646f9b1c3SMichael Lange /* Now add the incoming overlap points */ 84746f9b1c3SMichael Lange for (p = 0; p < nleaves; p++) { 84846f9b1c3SMichael Lange point = depthIdx[remoteDepths[p]]; 84946f9b1c3SMichael Lange ilocal[point] = point; 85046f9b1c3SMichael Lange iremote[point].index = overlapRemote[p].index; 85146f9b1c3SMichael Lange iremote[point].rank = overlapRemote[p].rank; 85246f9b1c3SMichael Lange depthIdx[remoteDepths[p]]++; 85346f9b1c3SMichael Lange } 8549566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointDepths, remoteDepths)); 85546f9b1c3SMichael Lange 8569566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, migrationSF)); 8579566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*migrationSF, "Overlap Migration SF")); 8589566063dSJacob Faibussowitsch PetscCall(PetscSFSetFromOptions(*migrationSF)); 8599566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8609566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*migrationSF, pEnd - pStart, newLeaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 86146f9b1c3SMichael Lange 8629566063dSJacob Faibussowitsch PetscCall(PetscFree3(depthRecv, depthShift, depthIdx)); 8633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 86470034214SMatthew G. Knepley } 86570034214SMatthew G. Knepley 866a9f1d5b2SMichael Lange /*@ 867f0e73a3dSToby Isaac DMPlexStratifyMigrationSF - Rearrange the leaves of a migration sf for stratification. 868a9f1d5b2SMichael Lange 869064ec1f3Sprj- Input Parameters: 870a9f1d5b2SMichael Lange + dm - The DM 871a9f1d5b2SMichael Lange - sf - A star forest with non-ordered leaves, usually defining a DM point migration 872a9f1d5b2SMichael Lange 873a9f1d5b2SMichael Lange Output Parameter: 874a9f1d5b2SMichael Lange . migrationSF - A star forest with added leaf indirection that ensures the resulting DM is stratified 875a9f1d5b2SMichael Lange 87620f4b53cSBarry Smith Level: developer 87720f4b53cSBarry Smith 878412e9a14SMatthew G. Knepley Note: 879412e9a14SMatthew G. Knepley This lexicographically sorts by (depth, cellType) 880412e9a14SMatthew G. Knepley 88120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 882a9f1d5b2SMichael Lange @*/ 883d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratifyMigrationSF(DM dm, PetscSF sf, PetscSF *migrationSF) 884d71ae5a4SJacob Faibussowitsch { 885a9f1d5b2SMichael Lange MPI_Comm comm; 8869852e123SBarry Smith PetscMPIInt rank, size; 887412e9a14SMatthew G. Knepley PetscInt d, ldepth, depth, dim, p, pStart, pEnd, nroots, nleaves; 888412e9a14SMatthew G. Knepley PetscSFNode *pointDepths, *remoteDepths; 889412e9a14SMatthew G. Knepley PetscInt *ilocal; 890a9f1d5b2SMichael Lange PetscInt *depthRecv, *depthShift, *depthIdx; 891412e9a14SMatthew G. Knepley PetscInt *ctRecv, *ctShift, *ctIdx; 892a9f1d5b2SMichael Lange const PetscSFNode *iremote; 893a9f1d5b2SMichael Lange 894a9f1d5b2SMichael Lange PetscFunctionBegin; 895a9f1d5b2SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8969566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 8979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 8989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 8999566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &ldepth)); 9009566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 901462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&ldepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 90263a3b9bcSJacob Faibussowitsch PetscCheck(!(ldepth >= 0) || !(depth != ldepth), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %" PetscInt_FMT " != %" PetscInt_FMT, ldepth, depth); 9039566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartStratSF, dm, 0, 0, 0)); 904a9f1d5b2SMichael Lange 905a9f1d5b2SMichael Lange /* Before building the migration SF we need to know the new stratum offsets */ 9069566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, &iremote)); 9079566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths)); 9087fab53ddSMatthew G. Knepley for (d = 0; d < depth + 1; ++d) { 9099566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 910f0e73a3dSToby Isaac for (p = pStart; p < pEnd; ++p) { 911412e9a14SMatthew G. Knepley DMPolytopeType ct; 912f0e73a3dSToby Isaac 9139566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 914412e9a14SMatthew G. Knepley pointDepths[p].index = d; 915412e9a14SMatthew G. Knepley pointDepths[p].rank = ct; 916f0e73a3dSToby Isaac } 917412e9a14SMatthew G. Knepley } 9189371c9d4SSatish Balay for (p = 0; p < nleaves; ++p) { 9199371c9d4SSatish Balay remoteDepths[p].index = -1; 9209371c9d4SSatish Balay remoteDepths[p].rank = -1; 9219371c9d4SSatish Balay } 9226497c311SBarry Smith PetscCall(PetscSFBcastBegin(sf, MPIU_SF_NODE, pointDepths, remoteDepths, MPI_REPLACE)); 9236497c311SBarry Smith PetscCall(PetscSFBcastEnd(sf, MPIU_SF_NODE, pointDepths, remoteDepths, MPI_REPLACE)); 924412e9a14SMatthew G. Knepley /* Count received points in each stratum and compute the internal strata shift */ 9259566063dSJacob Faibussowitsch PetscCall(PetscCalloc6(depth + 1, &depthRecv, depth + 1, &depthShift, depth + 1, &depthIdx, DM_NUM_POLYTOPES, &ctRecv, DM_NUM_POLYTOPES, &ctShift, DM_NUM_POLYTOPES, &ctIdx)); 926412e9a14SMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 927412e9a14SMatthew G. Knepley if (remoteDepths[p].rank < 0) { 928412e9a14SMatthew G. Knepley ++depthRecv[remoteDepths[p].index]; 929412e9a14SMatthew G. Knepley } else { 930412e9a14SMatthew G. Knepley ++ctRecv[remoteDepths[p].rank]; 931412e9a14SMatthew G. Knepley } 932412e9a14SMatthew G. Knepley } 933412e9a14SMatthew G. Knepley { 934412e9a14SMatthew G. Knepley PetscInt depths[4], dims[4], shift = 0, i, c; 935412e9a14SMatthew G. Knepley 9368238f61eSMatthew G. Knepley /* Cells (depth), Vertices (0), Faces (depth-1), Edges (1) 937476787b7SMatthew G. Knepley Consider DM_POLYTOPE_FV_GHOST, DM_POLYTOPE_INTERIOR_GHOST and DM_POLYTOPE_UNKNOWN_CELL as cells 9388238f61eSMatthew G. Knepley */ 9399371c9d4SSatish Balay depths[0] = depth; 9409371c9d4SSatish Balay depths[1] = 0; 9419371c9d4SSatish Balay depths[2] = depth - 1; 9429371c9d4SSatish Balay depths[3] = 1; 9439371c9d4SSatish Balay dims[0] = dim; 9449371c9d4SSatish Balay dims[1] = 0; 9459371c9d4SSatish Balay dims[2] = dim - 1; 9469371c9d4SSatish Balay dims[3] = 1; 947412e9a14SMatthew G. Knepley for (i = 0; i <= depth; ++i) { 948412e9a14SMatthew G. Knepley const PetscInt dep = depths[i]; 949412e9a14SMatthew G. Knepley const PetscInt dim = dims[i]; 950412e9a14SMatthew G. Knepley 951412e9a14SMatthew G. Knepley for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 952476787b7SMatthew 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; 953412e9a14SMatthew G. Knepley ctShift[c] = shift; 954412e9a14SMatthew G. Knepley shift += ctRecv[c]; 955412e9a14SMatthew G. Knepley } 956412e9a14SMatthew G. Knepley depthShift[dep] = shift; 957412e9a14SMatthew G. Knepley shift += depthRecv[dep]; 958412e9a14SMatthew G. Knepley } 959412e9a14SMatthew G. Knepley for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 960412e9a14SMatthew G. Knepley const PetscInt ctDim = DMPolytopeTypeGetDim((DMPolytopeType)c); 961412e9a14SMatthew G. Knepley 962b6555650SPierre Jolivet if ((ctDim < 0 || ctDim > dim) && c != DM_POLYTOPE_FV_GHOST && c != DM_POLYTOPE_INTERIOR_GHOST && c != DM_POLYTOPE_UNKNOWN_CELL) { 963412e9a14SMatthew G. Knepley ctShift[c] = shift; 964412e9a14SMatthew G. Knepley shift += ctRecv[c]; 965412e9a14SMatthew G. Knepley } 966412e9a14SMatthew G. Knepley } 967412e9a14SMatthew G. Knepley } 968a9f1d5b2SMichael Lange /* Derive a new local permutation based on stratified indices */ 9699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &ilocal)); 9707fab53ddSMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 971412e9a14SMatthew G. Knepley const DMPolytopeType ct = (DMPolytopeType)remoteDepths[p].rank; 9727fab53ddSMatthew G. Knepley 973412e9a14SMatthew G. Knepley ilocal[p] = ctShift[ct] + ctIdx[ct]; 974412e9a14SMatthew G. Knepley ++ctIdx[ct]; 975412e9a14SMatthew G. Knepley } 9769566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, migrationSF)); 9779566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*migrationSF, "Migration SF")); 9789566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*migrationSF, nroots, nleaves, ilocal, PETSC_OWN_POINTER, (PetscSFNode *)iremote, PETSC_COPY_VALUES)); 9799566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointDepths, remoteDepths)); 9809566063dSJacob Faibussowitsch PetscCall(PetscFree6(depthRecv, depthShift, depthIdx, ctRecv, ctShift, ctIdx)); 9819566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartStratSF, dm, 0, 0, 0)); 9823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 983a9f1d5b2SMichael Lange } 984a9f1d5b2SMichael Lange 98570034214SMatthew G. Knepley /*@ 98620f4b53cSBarry Smith DMPlexDistributeField - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 98770034214SMatthew G. Knepley 98820f4b53cSBarry Smith Collective 98970034214SMatthew G. Knepley 99070034214SMatthew G. Knepley Input Parameters: 99120f4b53cSBarry Smith + dm - The `DMPLEX` object 99220f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 99320f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 994cb15cd0eSMatthew G. Knepley - originalVec - The existing data in a local vector 99570034214SMatthew G. Knepley 99670034214SMatthew G. Knepley Output Parameters: 99720f4b53cSBarry Smith + newSection - The `PetscSF` describing the new data layout 998cb15cd0eSMatthew G. Knepley - newVec - The new data in a local vector 99970034214SMatthew G. Knepley 100070034214SMatthew G. Knepley Level: developer 100170034214SMatthew G. Knepley 100220f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeFieldIS()`, `DMPlexDistributeData()` 100370034214SMatthew G. Knepley @*/ 1004d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 1005d71ae5a4SJacob Faibussowitsch { 100670034214SMatthew G. Knepley PetscSF fieldSF; 100770034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize; 100870034214SMatthew G. Knepley PetscScalar *originalValues, *newValues; 100970034214SMatthew G. Knepley 101070034214SMatthew G. Knepley PetscFunctionBegin; 10119566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeField, dm, 0, 0, 0)); 10129566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 101370034214SMatthew G. Knepley 10149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 10159566063dSJacob Faibussowitsch PetscCall(VecSetSizes(newVec, fieldSize, PETSC_DETERMINE)); 10169566063dSJacob Faibussowitsch PetscCall(VecSetType(newVec, dm->vectype)); 101770034214SMatthew G. Knepley 10189566063dSJacob Faibussowitsch PetscCall(VecGetArray(originalVec, &originalValues)); 10199566063dSJacob Faibussowitsch PetscCall(VecGetArray(newVec, &newValues)); 10209566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 10219566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 10229566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues, MPI_REPLACE)); 10239566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues, MPI_REPLACE)); 10249566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 10259566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(newVec, &newValues)); 10269566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(originalVec, &originalValues)); 10279566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeField, dm, 0, 0, 0)); 10283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 102970034214SMatthew G. Knepley } 103070034214SMatthew G. Knepley 103170034214SMatthew G. Knepley /*@ 103220f4b53cSBarry Smith DMPlexDistributeFieldIS - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 103370034214SMatthew G. Knepley 103420f4b53cSBarry Smith Collective 103570034214SMatthew G. Knepley 103670034214SMatthew G. Knepley Input Parameters: 103720f4b53cSBarry Smith + dm - The `DMPLEX` object 103820f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 103920f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 104070034214SMatthew G. Knepley - originalIS - The existing data 104170034214SMatthew G. Knepley 104270034214SMatthew G. Knepley Output Parameters: 104320f4b53cSBarry Smith + newSection - The `PetscSF` describing the new data layout 104470034214SMatthew G. Knepley - newIS - The new data 104570034214SMatthew G. Knepley 104670034214SMatthew G. Knepley Level: developer 104770034214SMatthew G. Knepley 104820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexDistributeData()` 104970034214SMatthew G. Knepley @*/ 1050d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeFieldIS(DM dm, PetscSF pointSF, PetscSection originalSection, IS originalIS, PetscSection newSection, IS *newIS) 1051d71ae5a4SJacob Faibussowitsch { 105270034214SMatthew G. Knepley PetscSF fieldSF; 105370034214SMatthew G. Knepley PetscInt *newValues, *remoteOffsets, fieldSize; 105470034214SMatthew G. Knepley const PetscInt *originalValues; 105570034214SMatthew G. Knepley 105670034214SMatthew G. Knepley PetscFunctionBegin; 10579566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeField, dm, 0, 0, 0)); 10589566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 105970034214SMatthew G. Knepley 10609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 10619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(fieldSize, &newValues)); 106270034214SMatthew G. Knepley 10639566063dSJacob Faibussowitsch PetscCall(ISGetIndices(originalIS, &originalValues)); 10649566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 10659566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 10669566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, MPIU_INT, (PetscInt *)originalValues, newValues, MPI_REPLACE)); 10679566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, MPIU_INT, (PetscInt *)originalValues, newValues, MPI_REPLACE)); 10689566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 10699566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(originalIS, &originalValues)); 10709566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pointSF), fieldSize, newValues, PETSC_OWN_POINTER, newIS)); 10719566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeField, dm, 0, 0, 0)); 10723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 107370034214SMatthew G. Knepley } 107470034214SMatthew G. Knepley 107570034214SMatthew G. Knepley /*@ 107620f4b53cSBarry Smith DMPlexDistributeData - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 107770034214SMatthew G. Knepley 107820f4b53cSBarry Smith Collective 107970034214SMatthew G. Knepley 108070034214SMatthew G. Knepley Input Parameters: 108120f4b53cSBarry Smith + dm - The `DMPLEX` object 108220f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 108320f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 108470034214SMatthew G. Knepley . datatype - The type of data 108570034214SMatthew G. Knepley - originalData - The existing data 108670034214SMatthew G. Knepley 108770034214SMatthew G. Knepley Output Parameters: 108820f4b53cSBarry Smith + newSection - The `PetscSection` describing the new data layout 108970034214SMatthew G. Knepley - newData - The new data 109070034214SMatthew G. Knepley 109170034214SMatthew G. Knepley Level: developer 109270034214SMatthew G. Knepley 109320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeField()` 109470034214SMatthew G. Knepley @*/ 1095d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeData(DM dm, PetscSF pointSF, PetscSection originalSection, MPI_Datatype datatype, void *originalData, PetscSection newSection, void **newData) 1096d71ae5a4SJacob Faibussowitsch { 109770034214SMatthew G. Knepley PetscSF fieldSF; 109870034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize; 109970034214SMatthew G. Knepley PetscMPIInt dataSize; 110070034214SMatthew G. Knepley 110170034214SMatthew G. Knepley PetscFunctionBegin; 11029566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeData, dm, 0, 0, 0)); 11039566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 110470034214SMatthew G. Knepley 11059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 11069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_size(datatype, &dataSize)); 11079566063dSJacob Faibussowitsch PetscCall(PetscMalloc(fieldSize * dataSize, newData)); 110870034214SMatthew G. Knepley 11099566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 11109566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 11119566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, datatype, originalData, *newData, MPI_REPLACE)); 11129566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, datatype, originalData, *newData, MPI_REPLACE)); 11139566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 11149566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeData, dm, 0, 0, 0)); 11153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 111670034214SMatthew G. Knepley } 111770034214SMatthew G. Knepley 1118d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeCones(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel) 1119d71ae5a4SJacob Faibussowitsch { 112057508eceSPierre Jolivet DM_Plex *pmesh = (DM_Plex *)dmParallel->data; 1121cc71bff1SMichael Lange MPI_Comm comm; 1122cc71bff1SMichael Lange PetscSF coneSF; 1123cc71bff1SMichael Lange PetscSection originalConeSection, newConeSection; 1124ac04eaf7SToby Isaac PetscInt *remoteOffsets, *cones, *globCones, *newCones, newConesSize; 1125cc71bff1SMichael Lange PetscBool flg; 1126cc71bff1SMichael Lange 1127cc71bff1SMichael Lange PetscFunctionBegin; 1128cc71bff1SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 11290c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5); 11309566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeCones, dm, 0, 0, 0)); 1131cc71bff1SMichael Lange /* Distribute cone section */ 11329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 11339566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &originalConeSection)); 11349566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dmParallel, &newConeSection)); 11359566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(migrationSF, originalConeSection, &remoteOffsets, newConeSection)); 11369566063dSJacob Faibussowitsch PetscCall(DMSetUp(dmParallel)); 1137cc71bff1SMichael Lange /* Communicate and renumber cones */ 11389566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(migrationSF, originalConeSection, remoteOffsets, newConeSection, &coneSF)); 11399566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 11409566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 1141ac04eaf7SToby Isaac if (original) { 1142ac04eaf7SToby Isaac PetscInt numCones; 1143ac04eaf7SToby Isaac 11449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(originalConeSection, &numCones)); 11459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCones, &globCones)); 11469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(original, numCones, cones, globCones)); 1147367003a6SStefano Zampini } else { 1148ac04eaf7SToby Isaac globCones = cones; 1149ac04eaf7SToby Isaac } 11509566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dmParallel, &newCones)); 11519566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coneSF, MPIU_INT, globCones, newCones, MPI_REPLACE)); 11529566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coneSF, MPIU_INT, globCones, newCones, MPI_REPLACE)); 11531baa6e33SBarry Smith if (original) PetscCall(PetscFree(globCones)); 11549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newConeSection, &newConesSize)); 11559566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones)); 115676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 11573533c52bSMatthew G. Knepley PetscInt p; 11583533c52bSMatthew G. Knepley PetscBool valid = PETSC_TRUE; 11593533c52bSMatthew G. Knepley for (p = 0; p < newConesSize; ++p) { 11609371c9d4SSatish Balay if (newCones[p] < 0) { 11619371c9d4SSatish Balay valid = PETSC_FALSE; 11629371c9d4SSatish Balay PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Point %" PetscInt_FMT " not in overlap SF\n", PetscGlobalRank, p)); 11639371c9d4SSatish Balay } 11643533c52bSMatthew G. Knepley } 116528b400f6SJacob Faibussowitsch PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map"); 11663533c52bSMatthew G. Knepley } 11679566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-cones_view", &flg)); 1168cc71bff1SMichael Lange if (flg) { 11699566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Serial Cone Section:\n")); 11709566063dSJacob Faibussowitsch PetscCall(PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_(comm))); 11719566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Parallel Cone Section:\n")); 11729566063dSJacob Faibussowitsch PetscCall(PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_(comm))); 11739566063dSJacob Faibussowitsch PetscCall(PetscSFView(coneSF, NULL)); 1174cc71bff1SMichael Lange } 11759566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dm, &cones)); 11769566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dmParallel, &newCones)); 11779566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones, MPI_REPLACE)); 11789566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones, MPI_REPLACE)); 11799566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coneSF)); 11809566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeCones, dm, 0, 0, 0)); 1181eaf898f9SPatrick Sanan /* Create supports and stratify DMPlex */ 1182cc71bff1SMichael Lange { 1183cc71bff1SMichael Lange PetscInt pStart, pEnd; 1184cc71bff1SMichael Lange 11859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd)); 11869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(pmesh->supportSection, pStart, pEnd)); 1187cc71bff1SMichael Lange } 11889566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dmParallel)); 11899566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dmParallel)); 11901cf84007SMatthew G. Knepley { 11911cf84007SMatthew G. Knepley PetscBool useCone, useClosure, useAnchors; 11921cf84007SMatthew G. Knepley 11939566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 11949566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dmParallel, useCone, useClosure)); 11959566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors)); 11969566063dSJacob Faibussowitsch PetscCall(DMPlexSetAdjacencyUseAnchors(dmParallel, useAnchors)); 11971cf84007SMatthew G. Knepley } 11983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1199cc71bff1SMichael Lange } 1200cc71bff1SMichael Lange 1201d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeCoordinates(DM dm, PetscSF migrationSF, DM dmParallel) 1202d71ae5a4SJacob Faibussowitsch { 12030df0e737SMichael Lange MPI_Comm comm; 12049318fe57SMatthew G. Knepley DM cdm, cdmParallel; 12050df0e737SMichael Lange PetscSection originalCoordSection, newCoordSection; 12060df0e737SMichael Lange Vec originalCoordinates, newCoordinates; 12070df0e737SMichael Lange PetscInt bs; 12080df0e737SMichael Lange const char *name; 12094fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 12100df0e737SMichael Lange 12110df0e737SMichael Lange PetscFunctionBegin; 12120df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 12130c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3); 12140df0e737SMichael Lange 12159566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12166858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 12176858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dmParallel, &cdmParallel)); 12186858538eSMatthew G. Knepley PetscCall(DMCopyDisc(cdm, cdmParallel)); 12199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &originalCoordSection)); 12209566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmParallel, &newCoordSection)); 12219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &originalCoordinates)); 12220df0e737SMichael Lange if (originalCoordinates) { 12239566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates)); 12249566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalCoordinates, &name)); 12259566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)newCoordinates, name)); 12260df0e737SMichael Lange 12279566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates)); 12289566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmParallel, newCoordinates)); 12299566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(originalCoordinates, &bs)); 12309566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(newCoordinates, bs)); 12319566063dSJacob Faibussowitsch PetscCall(VecDestroy(&newCoordinates)); 12320df0e737SMichael Lange } 12336858538eSMatthew G. Knepley 12346858538eSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12354fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L)); 12364fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmParallel, maxCell, Lstart, L)); 12376858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdm)); 12386858538eSMatthew G. Knepley if (cdm) { 12396858538eSMatthew G. Knepley PetscCall(DMClone(dmParallel, &cdmParallel)); 12406858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmParallel, cdmParallel)); 12419566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(cdm, cdmParallel)); 12426858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmParallel)); 12436858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &originalCoordSection)); 12446858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &originalCoordinates)); 12456858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(comm, &newCoordSection)); 12466858538eSMatthew G. Knepley if (originalCoordinates) { 12476858538eSMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates)); 12486858538eSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)originalCoordinates, &name)); 12496858538eSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)newCoordinates, name)); 12506858538eSMatthew G. Knepley 12516858538eSMatthew G. Knepley PetscCall(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates)); 12526858538eSMatthew G. Knepley PetscCall(VecGetBlockSize(originalCoordinates, &bs)); 12536858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(newCoordinates, bs)); 12546858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(dmParallel, bs, newCoordSection)); 12556858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmParallel, newCoordinates)); 12566858538eSMatthew G. Knepley PetscCall(VecDestroy(&newCoordinates)); 12576858538eSMatthew G. Knepley } 12586858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&newCoordSection)); 12596858538eSMatthew G. Knepley } 12603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12610df0e737SMichael Lange } 12620df0e737SMichael Lange 1263d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeLabels(DM dm, PetscSF migrationSF, DM dmParallel) 1264d71ae5a4SJacob Faibussowitsch { 1265df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 12660df0e737SMichael Lange MPI_Comm comm; 12677980c9d4SMatthew G. Knepley DMLabel depthLabel; 12680df0e737SMichael Lange PetscMPIInt rank; 12697980c9d4SMatthew G. Knepley PetscInt depth, d, numLabels, numLocalLabels, l; 1270df0420ecSMatthew G. Knepley PetscBool hasLabels = PETSC_FALSE, lsendDepth, sendDepth; 1271df0420ecSMatthew G. Knepley PetscObjectState depthState = -1; 12720df0e737SMichael Lange 12730df0e737SMichael Lange PetscFunctionBegin; 12740df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 12750c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3); 12760c86c063SLisandro Dalcin 12779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeLabels, dm, 0, 0, 0)); 12789566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 12800df0e737SMichael Lange 1281df0420ecSMatthew G. Knepley /* If the user has changed the depth label, communicate it instead */ 12829566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 12839566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 12849566063dSJacob Faibussowitsch if (depthLabel) PetscCall(PetscObjectStateGet((PetscObject)depthLabel, &depthState)); 1285df0420ecSMatthew G. Knepley lsendDepth = mesh->depthState != depthState ? PETSC_TRUE : PETSC_FALSE; 12865440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lsendDepth, &sendDepth, 1, MPI_C_BOOL, MPI_LOR, comm)); 1287df0420ecSMatthew G. Knepley if (sendDepth) { 12889566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dmParallel, &dmParallel->depthLabel)); 12899566063dSJacob Faibussowitsch PetscCall(DMRemoveLabelBySelf(dmParallel, &dmParallel->depthLabel, PETSC_FALSE)); 1290df0420ecSMatthew G. Knepley } 1291d995df53SMatthew G. Knepley /* Everyone must have either the same number of labels, or none */ 12929566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLocalLabels)); 1293d995df53SMatthew G. Knepley numLabels = numLocalLabels; 12949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm)); 1295627847f0SMatthew G. Knepley if (numLabels == numLocalLabels) hasLabels = PETSC_TRUE; 12965d80c0bfSVaclav Hapla for (l = 0; l < numLabels; ++l) { 1297bdd2d751SMichael Lange DMLabel label = NULL, labelNew = NULL; 129883e10cb3SLisandro Dalcin PetscBool isDepth, lisOutput = PETSC_TRUE, isOutput; 1299d67d17b1SMatthew G. Knepley const char *name = NULL; 13000df0e737SMichael Lange 1301d67d17b1SMatthew G. Knepley if (hasLabels) { 13029566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(dm, l, &label)); 13030df0e737SMichael Lange /* Skip "depth" because it is recreated */ 13049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)label, &name)); 13059566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 1306bbcf679cSJacob Faibussowitsch } else { 1307bbcf679cSJacob Faibussowitsch isDepth = PETSC_FALSE; 1308d67d17b1SMatthew G. Knepley } 13095440e5dcSBarry Smith PetscCallMPI(MPI_Bcast(&isDepth, 1, MPI_C_BOOL, 0, comm)); 131083e10cb3SLisandro Dalcin if (isDepth && !sendDepth) continue; 13119566063dSJacob Faibussowitsch PetscCall(DMLabelDistribute(label, migrationSF, &labelNew)); 131283e10cb3SLisandro Dalcin if (isDepth) { 13137980c9d4SMatthew G. Knepley /* Put in any missing strata which can occur if users are managing the depth label themselves */ 13147980c9d4SMatthew G. Knepley PetscInt gdepth; 13157980c9d4SMatthew G. Knepley 1316462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&depth, &gdepth, 1, MPIU_INT, MPI_MAX, comm)); 131763a3b9bcSJacob Faibussowitsch PetscCheck(!(depth >= 0) || !(gdepth != depth), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %" PetscInt_FMT " != %" PetscInt_FMT, depth, gdepth); 13187980c9d4SMatthew G. Knepley for (d = 0; d <= gdepth; ++d) { 13197980c9d4SMatthew G. Knepley PetscBool has; 13207980c9d4SMatthew G. Knepley 13219566063dSJacob Faibussowitsch PetscCall(DMLabelHasStratum(labelNew, d, &has)); 13229566063dSJacob Faibussowitsch if (!has) PetscCall(DMLabelAddStratum(labelNew, d)); 13237980c9d4SMatthew G. Knepley } 13247980c9d4SMatthew G. Knepley } 13259566063dSJacob Faibussowitsch PetscCall(DMAddLabel(dmParallel, labelNew)); 132683e10cb3SLisandro Dalcin /* Put the output flag in the new label */ 13279566063dSJacob Faibussowitsch if (hasLabels) PetscCall(DMGetLabelOutput(dm, name, &lisOutput)); 13285440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lisOutput, &isOutput, 1, MPI_C_BOOL, MPI_LAND, comm)); 13299566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)labelNew, &name)); 13309566063dSJacob Faibussowitsch PetscCall(DMSetLabelOutput(dmParallel, name, isOutput)); 13319566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&labelNew)); 13320df0e737SMichael Lange } 1333695799ffSMatthew G. Knepley { 1334695799ffSMatthew G. Knepley DMLabel ctLabel; 1335695799ffSMatthew G. Knepley 1336695799ffSMatthew G. Knepley // Reset label for fast lookup 1337695799ffSMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dmParallel, &ctLabel)); 1338695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 1339695799ffSMatthew G. Knepley } 13409566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeLabels, dm, 0, 0, 0)); 13413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13420df0e737SMichael Lange } 13430df0e737SMichael Lange 1344d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeSetupTree(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel) 1345d71ae5a4SJacob Faibussowitsch { 134615078cd4SMichael Lange DM_Plex *mesh = (DM_Plex *)dm->data; 134757508eceSPierre Jolivet DM_Plex *pmesh = (DM_Plex *)dmParallel->data; 1348a6f36705SMichael Lange MPI_Comm comm; 1349a6f36705SMichael Lange DM refTree; 1350a6f36705SMichael Lange PetscSection origParentSection, newParentSection; 1351a6f36705SMichael Lange PetscInt *origParents, *origChildIDs; 1352a6f36705SMichael Lange PetscBool flg; 1353a6f36705SMichael Lange 1354a6f36705SMichael Lange PetscFunctionBegin; 1355a6f36705SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13560c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5); 13579566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 1358a6f36705SMichael Lange 1359a6f36705SMichael Lange /* Set up tree */ 13609566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 13619566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(dmParallel, refTree)); 13629566063dSJacob Faibussowitsch PetscCall(DMPlexGetTree(dm, &origParentSection, &origParents, &origChildIDs, NULL, NULL)); 1363a6f36705SMichael Lange if (origParentSection) { 1364a6f36705SMichael Lange PetscInt pStart, pEnd; 136508633170SToby Isaac PetscInt *newParents, *newChildIDs, *globParents; 1366a6f36705SMichael Lange PetscInt *remoteOffsetsParents, newParentSize; 1367a6f36705SMichael Lange PetscSF parentSF; 1368a6f36705SMichael Lange 13699566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmParallel, &pStart, &pEnd)); 13709566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmParallel), &newParentSection)); 13719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newParentSection, pStart, pEnd)); 13729566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(migrationSF, origParentSection, &remoteOffsetsParents, newParentSection)); 13739566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(migrationSF, origParentSection, remoteOffsetsParents, newParentSection, &parentSF)); 13749566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsParents)); 13759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newParentSection, &newParentSize)); 13769566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(newParentSize, &newParents, newParentSize, &newChildIDs)); 137708633170SToby Isaac if (original) { 137808633170SToby Isaac PetscInt numParents; 137908633170SToby Isaac 13809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(origParentSection, &numParents)); 13819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numParents, &globParents)); 13829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(original, numParents, origParents, globParents)); 13839371c9d4SSatish Balay } else { 138408633170SToby Isaac globParents = origParents; 138508633170SToby Isaac } 13869566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(parentSF, MPIU_INT, globParents, newParents, MPI_REPLACE)); 13879566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(parentSF, MPIU_INT, globParents, newParents, MPI_REPLACE)); 13881baa6e33SBarry Smith if (original) PetscCall(PetscFree(globParents)); 13899566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(parentSF, MPIU_INT, origChildIDs, newChildIDs, MPI_REPLACE)); 13909566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(parentSF, MPIU_INT, origChildIDs, newChildIDs, MPI_REPLACE)); 13919566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newParentSize, newParents, NULL, newParents)); 139276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 13934a54e071SToby Isaac PetscInt p; 13944a54e071SToby Isaac PetscBool valid = PETSC_TRUE; 13954a54e071SToby Isaac for (p = 0; p < newParentSize; ++p) { 13969371c9d4SSatish Balay if (newParents[p] < 0) { 13979371c9d4SSatish Balay valid = PETSC_FALSE; 13989371c9d4SSatish Balay PetscCall(PetscPrintf(PETSC_COMM_SELF, "Point %" PetscInt_FMT " not in overlap SF\n", p)); 13999371c9d4SSatish Balay } 14004a54e071SToby Isaac } 140128b400f6SJacob Faibussowitsch PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map"); 14024a54e071SToby Isaac } 14039566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-parents_view", &flg)); 1404a6f36705SMichael Lange if (flg) { 14059566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Serial Parent Section: \n")); 14069566063dSJacob Faibussowitsch PetscCall(PetscSectionView(origParentSection, PETSC_VIEWER_STDOUT_(comm))); 14079566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Parallel Parent Section: \n")); 14089566063dSJacob Faibussowitsch PetscCall(PetscSectionView(newParentSection, PETSC_VIEWER_STDOUT_(comm))); 14099566063dSJacob Faibussowitsch PetscCall(PetscSFView(parentSF, NULL)); 1410a6f36705SMichael Lange } 14119566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(dmParallel, newParentSection, newParents, newChildIDs)); 14129566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newParentSection)); 14139566063dSJacob Faibussowitsch PetscCall(PetscFree2(newParents, newChildIDs)); 14149566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&parentSF)); 1415a6f36705SMichael Lange } 141615078cd4SMichael Lange pmesh->useAnchors = mesh->useAnchors; 14173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1418a6f36705SMichael Lange } 14190df0e737SMichael Lange 142098ba2d7fSLawrence Mitchell /*@ 142120f4b53cSBarry Smith DMPlexSetPartitionBalance - Should distribution of the `DM` attempt to balance the shared point partition? 142298ba2d7fSLawrence Mitchell 142398ba2d7fSLawrence Mitchell Input Parameters: 142420f4b53cSBarry Smith + dm - The `DMPLEX` object 142598ba2d7fSLawrence Mitchell - flg - Balance the partition? 142698ba2d7fSLawrence Mitchell 142798ba2d7fSLawrence Mitchell Level: intermediate 142898ba2d7fSLawrence Mitchell 142920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetPartitionBalance()` 143098ba2d7fSLawrence Mitchell @*/ 1431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetPartitionBalance(DM dm, PetscBool flg) 1432d71ae5a4SJacob Faibussowitsch { 143398ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 143498ba2d7fSLawrence Mitchell 143598ba2d7fSLawrence Mitchell PetscFunctionBegin; 143698ba2d7fSLawrence Mitchell mesh->partitionBalance = flg; 14373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 143898ba2d7fSLawrence Mitchell } 143998ba2d7fSLawrence Mitchell 144098ba2d7fSLawrence Mitchell /*@ 144120f4b53cSBarry Smith DMPlexGetPartitionBalance - Does distribution of the `DM` attempt to balance the shared point partition? 144298ba2d7fSLawrence Mitchell 144398ba2d7fSLawrence Mitchell Input Parameter: 144420f4b53cSBarry Smith . dm - The `DMPLEX` object 144598ba2d7fSLawrence Mitchell 144698ba2d7fSLawrence Mitchell Output Parameter: 1447a2b725a8SWilliam Gropp . flg - Balance the partition? 144898ba2d7fSLawrence Mitchell 144998ba2d7fSLawrence Mitchell Level: intermediate 145098ba2d7fSLawrence Mitchell 145120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexSetPartitionBalance()` 145298ba2d7fSLawrence Mitchell @*/ 1453d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPartitionBalance(DM dm, PetscBool *flg) 1454d71ae5a4SJacob Faibussowitsch { 145598ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 145698ba2d7fSLawrence Mitchell 145798ba2d7fSLawrence Mitchell PetscFunctionBegin; 145898ba2d7fSLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14594f572ea9SToby Isaac PetscAssertPointer(flg, 2); 146098ba2d7fSLawrence Mitchell *flg = mesh->partitionBalance; 14613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 146298ba2d7fSLawrence Mitchell } 146398ba2d7fSLawrence Mitchell 1464fc02256fSLawrence Mitchell typedef struct { 1465fc02256fSLawrence Mitchell PetscInt vote, rank, index; 1466fc02256fSLawrence Mitchell } Petsc3Int; 1467fc02256fSLawrence Mitchell 1468fc02256fSLawrence Mitchell /* MaxLoc, but carry a third piece of information around */ 1469d71ae5a4SJacob Faibussowitsch static void MPIAPI MaxLocCarry(void *in_, void *inout_, PetscMPIInt *len_, MPI_Datatype *dtype) 1470d71ae5a4SJacob Faibussowitsch { 1471fc02256fSLawrence Mitchell Petsc3Int *a = (Petsc3Int *)inout_; 1472fc02256fSLawrence Mitchell Petsc3Int *b = (Petsc3Int *)in_; 1473fc02256fSLawrence Mitchell PetscInt i, len = *len_; 1474fc02256fSLawrence Mitchell for (i = 0; i < len; i++) { 1475fc02256fSLawrence Mitchell if (a[i].vote < b[i].vote) { 1476fc02256fSLawrence Mitchell a[i].vote = b[i].vote; 1477fc02256fSLawrence Mitchell a[i].rank = b[i].rank; 1478fc02256fSLawrence Mitchell a[i].index = b[i].index; 1479fc02256fSLawrence Mitchell } else if (a[i].vote <= b[i].vote) { 1480fc02256fSLawrence Mitchell if (a[i].rank >= b[i].rank) { 1481fc02256fSLawrence Mitchell a[i].rank = b[i].rank; 1482fc02256fSLawrence Mitchell a[i].index = b[i].index; 1483fc02256fSLawrence Mitchell } 1484fc02256fSLawrence Mitchell } 1485fc02256fSLawrence Mitchell } 1486fc02256fSLawrence Mitchell } 1487fc02256fSLawrence Mitchell 1488cc4c1da9SBarry Smith /*@ 148920f4b53cSBarry Smith DMPlexCreatePointSF - Build a point `PetscSF` from an `PetscSF` describing a point migration 1490f5bf2dbfSMichael Lange 1491064ec1f3Sprj- Input Parameters: 149220f4b53cSBarry Smith + dm - The source `DMPLEX` object 1493f5bf2dbfSMichael Lange . migrationSF - The star forest that describes the parallel point remapping 1494d8d19677SJose E. Roman - ownership - Flag causing a vote to determine point ownership 1495f5bf2dbfSMichael Lange 1496f5bf2dbfSMichael Lange Output Parameter: 149720f4b53cSBarry Smith . pointSF - The star forest describing the point overlap in the remapped `DM` 14983618482eSVaclav Hapla 1499f5bf2dbfSMichael Lange Level: developer 1500f5bf2dbfSMichael Lange 150120f4b53cSBarry Smith Note: 150220f4b53cSBarry Smith Output `pointSF` is guaranteed to have the array of local indices (leaves) sorted. 150320f4b53cSBarry Smith 150420f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 1505f5bf2dbfSMichael Lange @*/ 1506d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointSF(DM dm, PetscSF migrationSF, PetscBool ownership, PetscSF *pointSF) 1507d71ae5a4SJacob Faibussowitsch { 150823193802SMatthew G. Knepley PetscMPIInt rank, size; 15091627f6ccSMichael Lange PetscInt p, nroots, nleaves, idx, npointLeaves; 1510f5bf2dbfSMichael Lange PetscInt *pointLocal; 1511f5bf2dbfSMichael Lange const PetscInt *leaves; 1512f5bf2dbfSMichael Lange const PetscSFNode *roots; 1513f5bf2dbfSMichael Lange PetscSFNode *rootNodes, *leafNodes, *pointRemote; 151423193802SMatthew G. Knepley Vec shifts; 1515cae3e4f3SLawrence Mitchell const PetscInt numShifts = 13759; 151623193802SMatthew G. Knepley const PetscScalar *shift = NULL; 151723193802SMatthew G. Knepley const PetscBool shiftDebug = PETSC_FALSE; 151898ba2d7fSLawrence Mitchell PetscBool balance; 1519f5bf2dbfSMichael Lange 1520f5bf2dbfSMichael Lange PetscFunctionBegin; 1521f5bf2dbfSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 15229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 15249566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreatePointSF, dm, 0, 0, 0)); 1525907a3e9cSStefano Zampini PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), pointSF)); 1526907a3e9cSStefano Zampini PetscCall(PetscSFSetFromOptions(*pointSF)); 1527907a3e9cSStefano Zampini if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 1528f5bf2dbfSMichael Lange 15299566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitionBalance(dm, &balance)); 15309566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(migrationSF, &nroots, &nleaves, &leaves, &roots)); 15319566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &rootNodes, nleaves, &leafNodes)); 1532f5bf2dbfSMichael Lange if (ownership) { 1533fc02256fSLawrence Mitchell MPI_Op op; 1534fc02256fSLawrence Mitchell MPI_Datatype datatype; 1535fc02256fSLawrence Mitchell Petsc3Int *rootVote = NULL, *leafVote = NULL; 15366497c311SBarry Smith 153723193802SMatthew 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. */ 153898ba2d7fSLawrence Mitchell if (balance) { 153923193802SMatthew G. Knepley PetscRandom r; 154023193802SMatthew G. Knepley 15419566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_SELF, &r)); 15429566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(r, 0, 2467 * size)); 15439566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &shifts)); 15449566063dSJacob Faibussowitsch PetscCall(VecSetSizes(shifts, numShifts, numShifts)); 15459566063dSJacob Faibussowitsch PetscCall(VecSetType(shifts, VECSTANDARD)); 15469566063dSJacob Faibussowitsch PetscCall(VecSetRandom(shifts, r)); 15479566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&r)); 15489566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(shifts, &shift)); 154923193802SMatthew G. Knepley } 155023193802SMatthew G. Knepley 15519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nroots, &rootVote)); 15529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &leafVote)); 155323193802SMatthew G. Knepley /* Point ownership vote: Process with highest rank owns shared points */ 1554f5bf2dbfSMichael Lange for (p = 0; p < nleaves; ++p) { 155523193802SMatthew G. Knepley if (shiftDebug) { 15569371c9d4SSatish 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, 15579371c9d4SSatish Balay (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]), (rank + (shift ? (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]) : 0)) % size)); 155823193802SMatthew G. Knepley } 1559f5bf2dbfSMichael Lange /* Either put in a bid or we know we own it */ 1560fc02256fSLawrence Mitchell leafVote[p].vote = (rank + (shift ? (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]) : 0)) % size; 1561fc02256fSLawrence Mitchell leafVote[p].rank = rank; 1562fc02256fSLawrence Mitchell leafVote[p].index = p; 1563f5bf2dbfSMichael Lange } 1564f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) { 15651627f6ccSMichael Lange /* Root must not participate in the reduction, flag so that MAXLOC does not use */ 1566fc02256fSLawrence Mitchell rootVote[p].vote = -3; 1567fc02256fSLawrence Mitchell rootVote[p].rank = -3; 1568fc02256fSLawrence Mitchell rootVote[p].index = -3; 1569f5bf2dbfSMichael Lange } 15709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(3, MPIU_INT, &datatype)); 15719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&datatype)); 15729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(&MaxLocCarry, 1, &op)); 15739566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(migrationSF, datatype, leafVote, rootVote, op)); 15749566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(migrationSF, datatype, leafVote, rootVote, op)); 15759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&op)); 15769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&datatype)); 1577c091126eSLawrence Mitchell for (p = 0; p < nroots; p++) { 1578835f2295SStefano Zampini rootNodes[p].rank = rootVote[p].rank; 1579fc02256fSLawrence Mitchell rootNodes[p].index = rootVote[p].index; 1580c091126eSLawrence Mitchell } 15819566063dSJacob Faibussowitsch PetscCall(PetscFree(leafVote)); 15829566063dSJacob Faibussowitsch PetscCall(PetscFree(rootVote)); 1583f5bf2dbfSMichael Lange } else { 1584f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) { 1585f5bf2dbfSMichael Lange rootNodes[p].index = -1; 1586f5bf2dbfSMichael Lange rootNodes[p].rank = rank; 1587fc02256fSLawrence Mitchell } 1588f5bf2dbfSMichael Lange for (p = 0; p < nleaves; p++) { 1589f5bf2dbfSMichael Lange /* Write new local id into old location */ 1590ad540459SPierre Jolivet if (roots[p].rank == rank) rootNodes[roots[p].index].index = leaves ? leaves[p] : p; 1591f5bf2dbfSMichael Lange } 1592f5bf2dbfSMichael Lange } 15936497c311SBarry Smith PetscCall(PetscSFBcastBegin(migrationSF, MPIU_SF_NODE, rootNodes, leafNodes, MPI_REPLACE)); 15946497c311SBarry Smith PetscCall(PetscSFBcastEnd(migrationSF, MPIU_SF_NODE, rootNodes, leafNodes, MPI_REPLACE)); 1595f5bf2dbfSMichael Lange 159623193802SMatthew G. Knepley for (npointLeaves = 0, p = 0; p < nleaves; p++) { 1597b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) npointLeaves++; 159823193802SMatthew G. Knepley } 15999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npointLeaves, &pointLocal)); 16009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npointLeaves, &pointRemote)); 1601f5bf2dbfSMichael Lange for (idx = 0, p = 0; p < nleaves; p++) { 1602b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) { 16033618482eSVaclav Hapla /* Note that pointLocal is automatically sorted as it is sublist of 0, ..., nleaves-1 */ 1604f5bf2dbfSMichael Lange pointLocal[idx] = p; 1605f5bf2dbfSMichael Lange pointRemote[idx] = leafNodes[p]; 1606f5bf2dbfSMichael Lange idx++; 1607f5bf2dbfSMichael Lange } 1608f5bf2dbfSMichael Lange } 160923193802SMatthew G. Knepley if (shift) { 16109566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(shifts, &shift)); 16119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shifts)); 161223193802SMatthew G. Knepley } 16139566063dSJacob Faibussowitsch if (shiftDebug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), PETSC_STDOUT)); 16149566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*pointSF, nleaves, npointLeaves, pointLocal, PETSC_OWN_POINTER, pointRemote, PETSC_OWN_POINTER)); 16159566063dSJacob Faibussowitsch PetscCall(PetscFree2(rootNodes, leafNodes)); 16169566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreatePointSF, dm, 0, 0, 0)); 1617d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, *pointSF, PETSC_FALSE)); 16183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1619f5bf2dbfSMichael Lange } 1620f5bf2dbfSMichael Lange 1621cc4c1da9SBarry Smith /*@ 162220f4b53cSBarry Smith DMPlexMigrate - Migrates internal `DM` data over the supplied star forest 162315078cd4SMichael Lange 162420f4b53cSBarry Smith Collective 162583655b49SVáclav Hapla 1626064ec1f3Sprj- Input Parameters: 162720f4b53cSBarry Smith + dm - The source `DMPLEX` object 1628d8d19677SJose E. Roman - sf - The star forest communication context describing the migration pattern 162915078cd4SMichael Lange 163015078cd4SMichael Lange Output Parameter: 163120f4b53cSBarry Smith . targetDM - The target `DMPLEX` object 163215078cd4SMichael Lange 1633b9f40539SMichael Lange Level: intermediate 163415078cd4SMichael Lange 163520f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 163615078cd4SMichael Lange @*/ 1637d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMigrate(DM dm, PetscSF sf, DM targetDM) 1638d71ae5a4SJacob Faibussowitsch { 1639b9f40539SMichael Lange MPI_Comm comm; 1640cc1750acSStefano Zampini PetscInt dim, cdim, nroots; 1641b9f40539SMichael Lange PetscSF sfPoint; 164215078cd4SMichael Lange ISLocalToGlobalMapping ltogMigration; 1643ac04eaf7SToby Isaac ISLocalToGlobalMapping ltogOriginal = NULL; 164415078cd4SMichael Lange 164515078cd4SMichael Lange PetscFunctionBegin; 164615078cd4SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 16479566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Migrate, dm, 0, 0, 0)); 16489566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 16499566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 16509566063dSJacob Faibussowitsch PetscCall(DMSetDimension(targetDM, dim)); 16519566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 16529566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(targetDM, cdim)); 165315078cd4SMichael Lange 1654bfb0467fSMichael Lange /* Check for a one-to-all distribution pattern */ 16559566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 16569566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 1657bfb0467fSMichael Lange if (nroots >= 0) { 1658b9f40539SMichael Lange IS isOriginal; 1659ac04eaf7SToby Isaac PetscInt n, size, nleaves; 1660ac04eaf7SToby Isaac PetscInt *numbering_orig, *numbering_new; 1661367003a6SStefano Zampini 1662b9f40539SMichael Lange /* Get the original point numbering */ 16639566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &isOriginal)); 16649566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(isOriginal, <ogOriginal)); 16659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(ltogOriginal, &size)); 16669566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltogOriginal, (const PetscInt **)&numbering_orig)); 1667b9f40539SMichael Lange /* Convert to positive global numbers */ 16689371c9d4SSatish Balay for (n = 0; n < size; n++) { 16699371c9d4SSatish Balay if (numbering_orig[n] < 0) numbering_orig[n] = -(numbering_orig[n] + 1); 16709371c9d4SSatish Balay } 1671b9f40539SMichael Lange /* Derive the new local-to-global mapping from the old one */ 16729566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, NULL, NULL)); 16739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &numbering_new)); 16749566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, numbering_orig, numbering_new, MPI_REPLACE)); 16759566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, numbering_orig, numbering_new, MPI_REPLACE)); 16769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, nleaves, numbering_new, PETSC_OWN_POINTER, <ogMigration)); 16779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogOriginal, (const PetscInt **)&numbering_orig)); 16789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isOriginal)); 167915078cd4SMichael Lange } else { 1680bfb0467fSMichael Lange /* One-to-all distribution pattern: We can derive LToG from SF */ 16819566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateSF(sf, 0, <ogMigration)); 168215078cd4SMichael Lange } 1683a5a902f7SVaclav Hapla PetscCall(PetscObjectSetName((PetscObject)ltogMigration, "Point renumbering for DM migration")); 1684a5a902f7SVaclav Hapla PetscCall(ISLocalToGlobalMappingViewFromOptions(ltogMigration, (PetscObject)dm, "-partition_view")); 168515078cd4SMichael Lange /* Migrate DM data to target DM */ 16869566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeCones(dm, sf, ltogOriginal, ltogMigration, targetDM)); 16879566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeLabels(dm, sf, targetDM)); 16889566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeCoordinates(dm, sf, targetDM)); 16899566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetupTree(dm, sf, ltogOriginal, ltogMigration, targetDM)); 16909566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<ogOriginal)); 16919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<ogMigration)); 16929566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Migrate, dm, 0, 0, 0)); 16933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 169415078cd4SMichael Lange } 169515078cd4SMichael Lange 169600a1aa47SMatthew G. Knepley /*@ 169700a1aa47SMatthew G. Knepley DMPlexRemapMigrationSF - Rewrite the distribution SF to account for overlap 169800a1aa47SMatthew G. Knepley 169900a1aa47SMatthew G. Knepley Collective 170000a1aa47SMatthew G. Knepley 170100a1aa47SMatthew G. Knepley Input Parameters: 170200a1aa47SMatthew G. Knepley + sfOverlap - The `PetscSF` object just for the overlap 170300a1aa47SMatthew G. Knepley - sfMigration - The original distribution `PetscSF` object 170400a1aa47SMatthew G. Knepley 170500a1aa47SMatthew G. Knepley Output Parameters: 170600a1aa47SMatthew G. Knepley . sfMigrationNew - A rewritten `PetscSF` object that incorporates the overlap 170700a1aa47SMatthew G. Knepley 170800a1aa47SMatthew G. Knepley Level: developer 170900a1aa47SMatthew G. Knepley 171000a1aa47SMatthew G. Knepley .seealso: `DMPLEX`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()`, `DMPlexGetOverlap()` 171100a1aa47SMatthew G. Knepley @*/ 171200a1aa47SMatthew G. Knepley PetscErrorCode DMPlexRemapMigrationSF(PetscSF sfOverlap, PetscSF sfMigration, PetscSF *sfMigrationNew) 171300a1aa47SMatthew G. Knepley { 1714835f2295SStefano Zampini PetscSFNode *newRemote, *permRemote = NULL; 171500a1aa47SMatthew G. Knepley const PetscInt *oldLeaves; 171600a1aa47SMatthew G. Knepley const PetscSFNode *oldRemote; 171700a1aa47SMatthew G. Knepley PetscInt nroots, nleaves, noldleaves; 171800a1aa47SMatthew G. Knepley 171900a1aa47SMatthew G. Knepley PetscFunctionBegin; 172000a1aa47SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfMigration, &nroots, &noldleaves, &oldLeaves, &oldRemote)); 172100a1aa47SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfOverlap, NULL, &nleaves, NULL, NULL)); 172200a1aa47SMatthew G. Knepley PetscCall(PetscMalloc1(nleaves, &newRemote)); 172300a1aa47SMatthew G. Knepley /* oldRemote: original root point mapping to original leaf point 172400a1aa47SMatthew G. Knepley newRemote: original leaf point mapping to overlapped leaf point */ 172500a1aa47SMatthew G. Knepley if (oldLeaves) { 172600a1aa47SMatthew G. Knepley /* After stratification, the migration remotes may not be in root (canonical) order, so we reorder using the leaf numbering */ 172700a1aa47SMatthew G. Knepley PetscCall(PetscMalloc1(noldleaves, &permRemote)); 172800a1aa47SMatthew G. Knepley for (PetscInt l = 0; l < noldleaves; ++l) permRemote[oldLeaves[l]] = oldRemote[l]; 172900a1aa47SMatthew G. Knepley oldRemote = permRemote; 173000a1aa47SMatthew G. Knepley } 17316497c311SBarry Smith PetscCall(PetscSFBcastBegin(sfOverlap, MPIU_SF_NODE, oldRemote, newRemote, MPI_REPLACE)); 17326497c311SBarry Smith PetscCall(PetscSFBcastEnd(sfOverlap, MPIU_SF_NODE, oldRemote, newRemote, MPI_REPLACE)); 1733835f2295SStefano Zampini PetscCall(PetscFree(permRemote)); 173400a1aa47SMatthew G. Knepley PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)sfOverlap), sfMigrationNew)); 173500a1aa47SMatthew G. Knepley PetscCall(PetscSFSetGraph(*sfMigrationNew, nroots, nleaves, NULL, PETSC_OWN_POINTER, newRemote, PETSC_OWN_POINTER)); 173600a1aa47SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 173700a1aa47SMatthew G. Knepley } 173800a1aa47SMatthew G. Knepley 17395d83a8b1SBarry Smith /*@ 174070034214SMatthew G. Knepley DMPlexDistribute - Distributes the mesh and any associated sections. 174170034214SMatthew G. Knepley 174220f4b53cSBarry Smith Collective 174370034214SMatthew G. Knepley 1744064ec1f3Sprj- Input Parameters: 174520f4b53cSBarry Smith + dm - The original `DMPLEX` object 174670034214SMatthew G. Knepley - overlap - The overlap of partitions, 0 is the default 174770034214SMatthew G. Knepley 1748064ec1f3Sprj- Output Parameters: 174920f4b53cSBarry Smith + sf - The `PetscSF` used for point distribution, or `NULL` if not needed 175020f4b53cSBarry Smith - dmParallel - The distributed `DMPLEX` object 175170034214SMatthew G. Knepley 175270034214SMatthew G. Knepley Level: intermediate 175370034214SMatthew G. Knepley 175420f4b53cSBarry Smith Note: 175520f4b53cSBarry Smith If the mesh was not distributed, the output `dmParallel` will be `NULL`. 175620f4b53cSBarry Smith 175720f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function 175820f4b53cSBarry Smith representation on the mesh. 175920f4b53cSBarry Smith 176020f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexGetOverlap()` 176170034214SMatthew G. Knepley @*/ 1762ce78bad3SBarry Smith PetscErrorCode DMPlexDistribute(DM dm, PetscInt overlap, PeOp PetscSF *sf, DM *dmParallel) 1763d71ae5a4SJacob Faibussowitsch { 176470034214SMatthew G. Knepley MPI_Comm comm; 176515078cd4SMichael Lange PetscPartitioner partitioner; 1766f8987ae8SMichael Lange IS cellPart; 1767f8987ae8SMichael Lange PetscSection cellPartSection; 1768cf86098cSMatthew G. Knepley DM dmCoord; 1769f8987ae8SMichael Lange DMLabel lblPartition, lblMigration; 1770874ddda9SLisandro Dalcin PetscSF sfMigration, sfStratified, sfPoint; 177198ba2d7fSLawrence Mitchell PetscBool flg, balance; 1772874ddda9SLisandro Dalcin PetscMPIInt rank, size; 177370034214SMatthew G. Knepley 177470034214SMatthew G. Knepley PetscFunctionBegin; 177570034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1776d5c515a1SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 2); 17774f572ea9SToby Isaac if (sf) PetscAssertPointer(sf, 3); 17784f572ea9SToby Isaac PetscAssertPointer(dmParallel, 4); 177970034214SMatthew G. Knepley 17800c86c063SLisandro Dalcin if (sf) *sf = NULL; 17810c86c063SLisandro Dalcin *dmParallel = NULL; 17829566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 17839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 17849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 17853ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 178670034214SMatthew G. Knepley 17879566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Distribute, dm, 0, 0, 0)); 178815078cd4SMichael Lange /* Create cell partition */ 17899566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0)); 17909566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &cellPartSection)); 17919566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &partitioner)); 17929566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDMPlexPartition(partitioner, dm, NULL, cellPartSection, &cellPart)); 17939566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartSelf, dm, 0, 0, 0)); 1794f8987ae8SMichael Lange { 1795f8987ae8SMichael Lange /* Convert partition to DMLabel */ 1796825f8a23SLisandro Dalcin IS is; 1797825f8a23SLisandro Dalcin PetscHSetI ht; 1798f8987ae8SMichael Lange const PetscInt *points; 17998e330a33SStefano Zampini PetscInt *iranks; 18008e330a33SStefano Zampini PetscInt pStart, pEnd, proc, npoints, poff = 0, nranks; 1801825f8a23SLisandro Dalcin 18029566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point Partition", &lblPartition)); 1803825f8a23SLisandro Dalcin /* Preallocate strata */ 18049566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 18059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1806825f8a23SLisandro Dalcin for (proc = pStart; proc < pEnd; proc++) { 18079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints)); 18089566063dSJacob Faibussowitsch if (npoints) PetscCall(PetscHSetIAdd(ht, proc)); 1809825f8a23SLisandro Dalcin } 18109566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ht, &nranks)); 18119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nranks, &iranks)); 18129566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ht, &poff, iranks)); 18139566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 18149566063dSJacob Faibussowitsch PetscCall(DMLabelAddStrata(lblPartition, nranks, iranks)); 18159566063dSJacob Faibussowitsch PetscCall(PetscFree(iranks)); 1816825f8a23SLisandro Dalcin /* Inline DMPlexPartitionLabelClosure() */ 18179566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellPart, &points)); 18189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1819f8987ae8SMichael Lange for (proc = pStart; proc < pEnd; proc++) { 18209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints)); 1821825f8a23SLisandro Dalcin if (!npoints) continue; 18229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellPartSection, proc, &poff)); 18239566063dSJacob Faibussowitsch PetscCall(DMPlexClosurePoints_Private(dm, npoints, points + poff, &is)); 18249566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(lblPartition, proc, is)); 18259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1826f8987ae8SMichael Lange } 18279566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellPart, &points)); 1828f8987ae8SMichael Lange } 18299566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartSelf, dm, 0, 0, 0)); 18306e203dd9SStefano Zampini 18319566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point migration", &lblMigration)); 18329566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelInvert(dm, lblPartition, NULL, lblMigration)); 18333ac0285dSStefano Zampini PetscCall(DMPlexPartitionLabelCreateSF(dm, lblMigration, PETSC_TRUE, &sfMigration)); 18349566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, sfMigration, &sfStratified)); 18359566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration)); 183643f7d02bSMichael Lange sfMigration = sfStratified; 18379566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sfMigration)); 18389566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0)); 18399566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-partition_view", &flg)); 184070034214SMatthew G. Knepley if (flg) { 18419566063dSJacob Faibussowitsch PetscCall(DMLabelView(lblPartition, PETSC_VIEWER_STDOUT_(comm))); 18429566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfMigration, PETSC_VIEWER_STDOUT_(comm))); 184370034214SMatthew G. Knepley } 1844f8987ae8SMichael Lange 184515078cd4SMichael Lange /* Create non-overlapping parallel DM and migrate internal data */ 18469566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, dmParallel)); 18479566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*dmParallel, "Parallel Mesh")); 18489566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(dm, sfMigration, *dmParallel)); 184970034214SMatthew G. Knepley 1850a157612eSMichael Lange /* Build the point SF without overlap */ 18519566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitionBalance(dm, &balance)); 18529566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitionBalance(*dmParallel, balance)); 18539566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*dmParallel, sfMigration, PETSC_TRUE, &sfPoint)); 18549566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*dmParallel, sfPoint)); 18555f06a3ddSJed Brown PetscCall(DMPlexMigrateIsoperiodicFaceSF_Internal(dm, *dmParallel, sfMigration)); 18569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dmParallel, &dmCoord)); 18579566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 18589566063dSJacob Faibussowitsch if (flg) PetscCall(PetscSFView(sfPoint, NULL)); 185970034214SMatthew G. Knepley 1860a157612eSMichael Lange if (overlap > 0) { 186115078cd4SMichael Lange DM dmOverlap; 186215078cd4SMichael Lange PetscSF sfOverlap, sfOverlapPoint; 1863524e35f8SStefano Zampini 1864a157612eSMichael Lange /* Add the partition overlap to the distributed DM */ 18659566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeOverlap(*dmParallel, overlap, &sfOverlap, &dmOverlap)); 18669566063dSJacob Faibussowitsch PetscCall(DMDestroy(dmParallel)); 1867a157612eSMichael Lange *dmParallel = dmOverlap; 1868c389ea9fSToby Isaac if (flg) { 18699566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Overlap Migration SF:\n")); 18709566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfOverlap, NULL)); 1871c389ea9fSToby Isaac } 187243331d4aSMichael Lange 1873f8987ae8SMichael Lange /* Re-map the migration SF to establish the full migration pattern */ 187400a1aa47SMatthew G. Knepley PetscCall(DMPlexRemapMigrationSF(sfOverlap, sfMigration, &sfOverlapPoint)); 18759566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfOverlap)); 18769566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration)); 187715078cd4SMichael Lange sfMigration = sfOverlapPoint; 1878c389ea9fSToby Isaac } 1879bf5244c7SMatthew G. Knepley /* Cleanup Partition */ 18809566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblPartition)); 18819566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblMigration)); 18829566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cellPartSection)); 18839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellPart)); 188412a88998SMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *dmParallel)); 188512a88998SMatthew G. Knepley // Create sfNatural, need discretization information 18869566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *dmParallel)); 18875d2873a6SJames Wright if (dm->localSection) { 18885d2873a6SJames Wright PetscSection psection; 18895d2873a6SJames Wright PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &psection)); 18905d2873a6SJames Wright PetscCall(PetscSFDistributeSection(sfMigration, dm->localSection, NULL, psection)); 18915d2873a6SJames Wright PetscCall(DMSetLocalSection(*dmParallel, psection)); 18925d2873a6SJames Wright PetscCall(PetscSectionDestroy(&psection)); 18935d2873a6SJames Wright } 189466fe0bfeSMatthew G. Knepley if (dm->useNatural) { 189566fe0bfeSMatthew G. Knepley PetscSection section; 189666fe0bfeSMatthew G. Knepley 1897fc6a3818SBlaise Bourdin PetscCall(DMSetUseNatural(*dmParallel, PETSC_TRUE)); 1898fc6a3818SBlaise Bourdin PetscCall(DMGetLocalSection(dm, §ion)); 1899fc6a3818SBlaise Bourdin 190016635c05SJames Wright /* If DM has useNatural = PETSC_TRUE, but no sfNatural is set, the DM's Section is considered natural */ 19018aee0f92SAlexis Marboeuf /* sfMigration and sfNatural are respectively the point and dofs SFs mapping to this natural DM */ 1902fc6a3818SBlaise Bourdin /* Compose with a previous sfNatural if present */ 1903fc6a3818SBlaise Bourdin if (dm->sfNatural) { 190416635c05SJames Wright PetscCall(DMPlexMigrateGlobalToNaturalSF(dm, *dmParallel, dm->sfNatural, sfMigration, &(*dmParallel)->sfNatural)); 1905fc6a3818SBlaise Bourdin } else { 1906fc6a3818SBlaise Bourdin PetscCall(DMPlexCreateGlobalToNaturalSF(*dmParallel, section, sfMigration, &(*dmParallel)->sfNatural)); 1907fc6a3818SBlaise Bourdin } 19088aee0f92SAlexis Marboeuf /* Compose with a previous sfMigration if present */ 19098aee0f92SAlexis Marboeuf if (dm->sfMigration) { 19108aee0f92SAlexis Marboeuf PetscSF naturalPointSF; 19118aee0f92SAlexis Marboeuf 19128aee0f92SAlexis Marboeuf PetscCall(PetscSFCompose(dm->sfMigration, sfMigration, &naturalPointSF)); 19138aee0f92SAlexis Marboeuf PetscCall(PetscSFDestroy(&sfMigration)); 19148aee0f92SAlexis Marboeuf sfMigration = naturalPointSF; 19158aee0f92SAlexis Marboeuf } 191666fe0bfeSMatthew G. Knepley } 1917721cbd76SMatthew G. Knepley /* Cleanup */ 19189371c9d4SSatish Balay if (sf) { 19199371c9d4SSatish Balay *sf = sfMigration; 19209371c9d4SSatish Balay } else PetscCall(PetscSFDestroy(&sfMigration)); 19219566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 19229566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Distribute, dm, 0, 0, 0)); 19233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 192470034214SMatthew G. Knepley } 1925a157612eSMichael Lange 1926907a3e9cSStefano Zampini PetscErrorCode DMPlexDistributeOverlap_Internal(DM dm, PetscInt overlap, MPI_Comm newcomm, const char *ovlboundary, PetscSF *sf, DM *dmOverlap) 1927907a3e9cSStefano Zampini { 1928907a3e9cSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 1929907a3e9cSStefano Zampini MPI_Comm comm; 1930907a3e9cSStefano Zampini PetscMPIInt size, rank; 1931907a3e9cSStefano Zampini PetscSection rootSection, leafSection; 1932907a3e9cSStefano Zampini IS rootrank, leafrank; 1933907a3e9cSStefano Zampini DM dmCoord; 1934907a3e9cSStefano Zampini DMLabel lblOverlap; 1935907a3e9cSStefano Zampini PetscSF sfOverlap, sfStratified, sfPoint; 1936907a3e9cSStefano Zampini PetscBool clear_ovlboundary; 1937907a3e9cSStefano Zampini 1938907a3e9cSStefano Zampini PetscFunctionBegin; 1939907a3e9cSStefano Zampini if (sf) *sf = NULL; 1940907a3e9cSStefano Zampini *dmOverlap = NULL; 1941907a3e9cSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 1942907a3e9cSStefano Zampini PetscCallMPI(MPI_Comm_size(comm, &size)); 1943907a3e9cSStefano Zampini PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1944907a3e9cSStefano Zampini if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 1945907a3e9cSStefano Zampini { 1946907a3e9cSStefano Zampini // We need to get options for the _already_distributed mesh, so it must be done here 1947907a3e9cSStefano Zampini PetscInt overlap; 1948907a3e9cSStefano Zampini const char *prefix; 1949907a3e9cSStefano Zampini char oldPrefix[PETSC_MAX_PATH_LEN]; 1950907a3e9cSStefano Zampini 1951907a3e9cSStefano Zampini oldPrefix[0] = '\0'; 1952907a3e9cSStefano Zampini PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 1953907a3e9cSStefano Zampini PetscCall(PetscStrncpy(oldPrefix, prefix, sizeof(oldPrefix))); 1954907a3e9cSStefano Zampini PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, "dist_")); 1955907a3e9cSStefano Zampini PetscCall(DMPlexGetOverlap(dm, &overlap)); 1956907a3e9cSStefano Zampini PetscObjectOptionsBegin((PetscObject)dm); 1957907a3e9cSStefano Zampini PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 1958907a3e9cSStefano Zampini PetscOptionsEnd(); 1959907a3e9cSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix[0] == '\0' ? NULL : oldPrefix)); 1960907a3e9cSStefano Zampini } 1961907a3e9cSStefano Zampini if (ovlboundary) { 1962907a3e9cSStefano Zampini PetscBool flg; 1963907a3e9cSStefano Zampini PetscCall(DMHasLabel(dm, ovlboundary, &flg)); 1964907a3e9cSStefano Zampini if (!flg) { 1965907a3e9cSStefano Zampini DMLabel label; 1966907a3e9cSStefano Zampini 1967907a3e9cSStefano Zampini PetscCall(DMCreateLabel(dm, ovlboundary)); 1968907a3e9cSStefano Zampini PetscCall(DMGetLabel(dm, ovlboundary, &label)); 1969907a3e9cSStefano Zampini PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label)); 1970907a3e9cSStefano Zampini clear_ovlboundary = PETSC_TRUE; 1971907a3e9cSStefano Zampini } 1972907a3e9cSStefano Zampini } 1973907a3e9cSStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 1974907a3e9cSStefano Zampini /* Compute point overlap with neighbouring processes on the distributed DM */ 1975907a3e9cSStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0)); 1976907a3e9cSStefano Zampini PetscCall(PetscSectionCreate(newcomm, &rootSection)); 1977907a3e9cSStefano Zampini PetscCall(PetscSectionCreate(newcomm, &leafSection)); 1978907a3e9cSStefano Zampini PetscCall(DMPlexDistributeOwnership(dm, rootSection, &rootrank, leafSection, &leafrank)); 1979907a3e9cSStefano Zampini if (mesh->numOvLabels) PetscCall(DMPlexCreateOverlapLabelFromLabels(dm, mesh->numOvLabels, mesh->ovLabels, mesh->ovValues, mesh->numOvExLabels, mesh->ovExLabels, mesh->ovExValues, rootSection, rootrank, leafSection, leafrank, &lblOverlap)); 1980907a3e9cSStefano Zampini else PetscCall(DMPlexCreateOverlapLabel(dm, overlap, rootSection, rootrank, leafSection, leafrank, &lblOverlap)); 1981907a3e9cSStefano Zampini /* Convert overlap label to stratified migration SF */ 19823ac0285dSStefano Zampini PetscCall(DMPlexPartitionLabelCreateSF(dm, lblOverlap, PETSC_FALSE, &sfOverlap)); 1983907a3e9cSStefano Zampini PetscCall(DMPlexStratifyMigrationSF(dm, sfOverlap, &sfStratified)); 1984907a3e9cSStefano Zampini PetscCall(PetscSFDestroy(&sfOverlap)); 1985907a3e9cSStefano Zampini sfOverlap = sfStratified; 1986907a3e9cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)sfOverlap, "Overlap SF")); 1987907a3e9cSStefano Zampini PetscCall(PetscSFSetFromOptions(sfOverlap)); 1988907a3e9cSStefano Zampini 1989907a3e9cSStefano Zampini PetscCall(PetscSectionDestroy(&rootSection)); 1990907a3e9cSStefano Zampini PetscCall(PetscSectionDestroy(&leafSection)); 1991907a3e9cSStefano Zampini PetscCall(ISDestroy(&rootrank)); 1992907a3e9cSStefano Zampini PetscCall(ISDestroy(&leafrank)); 1993907a3e9cSStefano Zampini PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0)); 1994907a3e9cSStefano Zampini 1995907a3e9cSStefano Zampini /* Build the overlapping DM */ 1996907a3e9cSStefano Zampini PetscCall(DMPlexCreate(newcomm, dmOverlap)); 1997907a3e9cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*dmOverlap, "Parallel Mesh")); 1998907a3e9cSStefano Zampini PetscCall(DMPlexMigrate(dm, sfOverlap, *dmOverlap)); 1999907a3e9cSStefano Zampini /* Store the overlap in the new DM */ 2000907a3e9cSStefano Zampini PetscCall(DMPlexSetOverlap_Plex(*dmOverlap, dm, overlap)); 2001907a3e9cSStefano Zampini /* Build the new point SF */ 2002907a3e9cSStefano Zampini PetscCall(DMPlexCreatePointSF(*dmOverlap, sfOverlap, PETSC_FALSE, &sfPoint)); 2003907a3e9cSStefano Zampini PetscCall(DMSetPointSF(*dmOverlap, sfPoint)); 2004907a3e9cSStefano Zampini PetscCall(DMGetCoordinateDM(*dmOverlap, &dmCoord)); 2005907a3e9cSStefano Zampini if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 2006907a3e9cSStefano Zampini PetscCall(DMGetCellCoordinateDM(*dmOverlap, &dmCoord)); 2007907a3e9cSStefano Zampini if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 2008907a3e9cSStefano Zampini PetscCall(PetscSFDestroy(&sfPoint)); 2009907a3e9cSStefano Zampini PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *dmOverlap)); 2010907a3e9cSStefano Zampini /* TODO: labels stored inside the DS for regions should be handled here */ 2011907a3e9cSStefano Zampini PetscCall(DMCopyDisc(dm, *dmOverlap)); 2012907a3e9cSStefano Zampini /* Cleanup overlap partition */ 2013907a3e9cSStefano Zampini PetscCall(DMLabelDestroy(&lblOverlap)); 2014907a3e9cSStefano Zampini if (sf) *sf = sfOverlap; 2015907a3e9cSStefano Zampini else PetscCall(PetscSFDestroy(&sfOverlap)); 2016907a3e9cSStefano Zampini if (ovlboundary) { 2017907a3e9cSStefano Zampini DMLabel label; 2018907a3e9cSStefano Zampini PetscBool flg; 2019907a3e9cSStefano Zampini 2020907a3e9cSStefano Zampini if (clear_ovlboundary) PetscCall(DMRemoveLabel(dm, ovlboundary, NULL)); 2021907a3e9cSStefano Zampini PetscCall(DMHasLabel(*dmOverlap, ovlboundary, &flg)); 202200045ab3SPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing %s label", ovlboundary); 2023907a3e9cSStefano Zampini PetscCall(DMGetLabel(*dmOverlap, ovlboundary, &label)); 2024907a3e9cSStefano Zampini PetscCall(DMPlexMarkBoundaryFaces_Internal(*dmOverlap, 1, 0, label, PETSC_TRUE)); 2025907a3e9cSStefano Zampini } 2026907a3e9cSStefano Zampini PetscCall(PetscLogEventEnd(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 2027907a3e9cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2028907a3e9cSStefano Zampini } 2029907a3e9cSStefano Zampini 20305d83a8b1SBarry Smith /*@ 203120f4b53cSBarry Smith DMPlexDistributeOverlap - Add partition overlap to a distributed non-overlapping `DM`. 2032a157612eSMichael Lange 203320f4b53cSBarry Smith Collective 2034a157612eSMichael Lange 2035064ec1f3Sprj- Input Parameters: 203620f4b53cSBarry Smith + dm - The non-overlapping distributed `DMPLEX` object 203757fe9a49SVaclav Hapla - overlap - The overlap of partitions (the same on all ranks) 2038a157612eSMichael Lange 2039064ec1f3Sprj- Output Parameters: 2040f13dfd9eSBarry Smith + sf - The `PetscSF` used for point distribution, or pass `NULL` if not needed 2041f13dfd9eSBarry Smith - dmOverlap - The overlapping distributed `DMPLEX` object 2042a157612eSMichael Lange 2043c506a872SMatthew G. Knepley Options Database Keys: 2044c506a872SMatthew G. Knepley + -dm_plex_overlap_labels <name1,name2,...> - List of overlap label names 2045c506a872SMatthew G. Knepley . -dm_plex_overlap_values <int1,int2,...> - List of overlap label values 2046c506a872SMatthew G. Knepley . -dm_plex_overlap_exclude_label <name> - Label used to exclude points from overlap 2047c506a872SMatthew G. Knepley - -dm_plex_overlap_exclude_value <int> - Label value used to exclude points from overlap 2048c506a872SMatthew G. Knepley 2049dccdeccaSVaclav Hapla Level: advanced 2050a157612eSMichael Lange 205120f4b53cSBarry Smith Notes: 205220f4b53cSBarry Smith If the mesh was not distributed, the return value is `NULL`. 205320f4b53cSBarry Smith 205420f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function 205520f4b53cSBarry Smith representation on the mesh. 205620f4b53cSBarry Smith 205720f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMPlexCreateOverlapLabel()`, `DMPlexGetOverlap()` 2058a157612eSMichael Lange @*/ 2059ce78bad3SBarry Smith PetscErrorCode DMPlexDistributeOverlap(DM dm, PetscInt overlap, PeOp PetscSF *sf, DM *dmOverlap) 2060d71ae5a4SJacob Faibussowitsch { 2061a157612eSMichael Lange PetscFunctionBegin; 2062a157612eSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 206357fe9a49SVaclav Hapla PetscValidLogicalCollectiveInt(dm, overlap, 2); 20644f572ea9SToby Isaac if (sf) PetscAssertPointer(sf, 3); 20654f572ea9SToby Isaac PetscAssertPointer(dmOverlap, 4); 2066907a3e9cSStefano Zampini PetscCall(DMPlexDistributeOverlap_Internal(dm, overlap, PetscObjectComm((PetscObject)dm), NULL, sf, dmOverlap)); 20673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2068a157612eSMichael Lange } 20696462276dSToby Isaac 2070d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap_Plex(DM dm, PetscInt *overlap) 2071d71ae5a4SJacob Faibussowitsch { 2072cb54e036SVaclav Hapla DM_Plex *mesh = (DM_Plex *)dm->data; 2073cb54e036SVaclav Hapla 2074cb54e036SVaclav Hapla PetscFunctionBegin; 2075cb54e036SVaclav Hapla *overlap = mesh->overlap; 20763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2077cb54e036SVaclav Hapla } 2078cb54e036SVaclav Hapla 2079d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap_Plex(DM dm, DM dmSrc, PetscInt overlap) 2080d71ae5a4SJacob Faibussowitsch { 208160667520SVaclav Hapla DM_Plex *mesh = NULL; 208260667520SVaclav Hapla DM_Plex *meshSrc = NULL; 208360667520SVaclav Hapla 208460667520SVaclav Hapla PetscFunctionBegin; 208560667520SVaclav Hapla PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 208660667520SVaclav Hapla mesh = (DM_Plex *)dm->data; 208760667520SVaclav Hapla if (dmSrc) { 208860667520SVaclav Hapla PetscValidHeaderSpecificType(dmSrc, DM_CLASSID, 2, DMPLEX); 208960667520SVaclav Hapla meshSrc = (DM_Plex *)dmSrc->data; 20909ed9361bSToby Isaac mesh->overlap = meshSrc->overlap; 20919ed9361bSToby Isaac } else { 20929ed9361bSToby Isaac mesh->overlap = 0; 209360667520SVaclav Hapla } 20949ed9361bSToby Isaac mesh->overlap += overlap; 20953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 209660667520SVaclav Hapla } 209760667520SVaclav Hapla 2098cb54e036SVaclav Hapla /*@ 2099c506a872SMatthew G. Knepley DMPlexGetOverlap - Get the width of the cell overlap 2100cb54e036SVaclav Hapla 210120f4b53cSBarry Smith Not Collective 2102cb54e036SVaclav Hapla 2103cb54e036SVaclav Hapla Input Parameter: 210420f4b53cSBarry Smith . dm - The `DM` 2105cb54e036SVaclav Hapla 2106064ec1f3Sprj- Output Parameter: 2107c506a872SMatthew G. Knepley . overlap - the width of the cell overlap 2108cb54e036SVaclav Hapla 2109cb54e036SVaclav Hapla Level: intermediate 2110cb54e036SVaclav Hapla 211120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexSetOverlap()`, `DMPlexDistribute()` 2112cb54e036SVaclav Hapla @*/ 2113d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap(DM dm, PetscInt *overlap) 2114d71ae5a4SJacob Faibussowitsch { 2115cb54e036SVaclav Hapla PetscFunctionBegin; 2116cb54e036SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21174f572ea9SToby Isaac PetscAssertPointer(overlap, 2); 2118cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexGetOverlap_C", (DM, PetscInt *), (dm, overlap)); 21193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2120cb54e036SVaclav Hapla } 2121cb54e036SVaclav Hapla 2122c506a872SMatthew G. Knepley /*@ 2123c506a872SMatthew G. Knepley DMPlexSetOverlap - Set the width of the cell overlap 2124c506a872SMatthew G. Knepley 212520f4b53cSBarry Smith Logically Collective 2126c506a872SMatthew G. Knepley 2127c506a872SMatthew G. Knepley Input Parameters: 212820f4b53cSBarry Smith + dm - The `DM` 212920f4b53cSBarry Smith . dmSrc - The `DM` that produced this one, or `NULL` 2130c506a872SMatthew G. Knepley - overlap - the width of the cell overlap 2131c506a872SMatthew G. Knepley 2132c506a872SMatthew G. Knepley Level: intermediate 2133c506a872SMatthew G. Knepley 213420f4b53cSBarry Smith Note: 213520f4b53cSBarry Smith The overlap from `dmSrc` is added to `dm` 213620f4b53cSBarry Smith 213720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexGetOverlap()`, `DMPlexDistribute()` 2138c506a872SMatthew G. Knepley @*/ 2139d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap(DM dm, DM dmSrc, PetscInt overlap) 2140d71ae5a4SJacob Faibussowitsch { 2141c506a872SMatthew G. Knepley PetscFunctionBegin; 2142c506a872SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2143c506a872SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 3); 2144c506a872SMatthew G. Knepley PetscTryMethod(dm, "DMPlexSetOverlap_C", (DM, DM, PetscInt), (dm, dmSrc, overlap)); 21453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2146c506a872SMatthew G. Knepley } 2147c506a872SMatthew G. Knepley 2148d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault_Plex(DM dm, PetscBool dist) 2149d71ae5a4SJacob Faibussowitsch { 2150e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2151e600fa54SMatthew G. Knepley 2152e600fa54SMatthew G. Knepley PetscFunctionBegin; 2153e600fa54SMatthew G. Knepley mesh->distDefault = dist; 21543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2155e600fa54SMatthew G. Knepley } 2156e600fa54SMatthew G. Knepley 2157e600fa54SMatthew G. Knepley /*@ 215820f4b53cSBarry Smith DMPlexDistributeSetDefault - Set flag indicating whether the `DM` should be distributed by default 2159e600fa54SMatthew G. Knepley 216020f4b53cSBarry Smith Logically Collective 2161e600fa54SMatthew G. Knepley 2162e600fa54SMatthew G. Knepley Input Parameters: 216320f4b53cSBarry Smith + dm - The `DM` 2164e600fa54SMatthew G. Knepley - dist - Flag for distribution 2165e600fa54SMatthew G. Knepley 2166e600fa54SMatthew G. Knepley Level: intermediate 2167e600fa54SMatthew G. Knepley 216820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributeGetDefault()`, `DMPlexDistribute()` 2169e600fa54SMatthew G. Knepley @*/ 2170d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault(DM dm, PetscBool dist) 2171d71ae5a4SJacob Faibussowitsch { 2172e600fa54SMatthew G. Knepley PetscFunctionBegin; 2173e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2174e600fa54SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, dist, 2); 2175cac4c232SBarry Smith PetscTryMethod(dm, "DMPlexDistributeSetDefault_C", (DM, PetscBool), (dm, dist)); 21763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2177e600fa54SMatthew G. Knepley } 2178e600fa54SMatthew G. Knepley 2179d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault_Plex(DM dm, PetscBool *dist) 2180d71ae5a4SJacob Faibussowitsch { 2181e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2182e600fa54SMatthew G. Knepley 2183e600fa54SMatthew G. Knepley PetscFunctionBegin; 2184e600fa54SMatthew G. Knepley *dist = mesh->distDefault; 21853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2186e600fa54SMatthew G. Knepley } 2187e600fa54SMatthew G. Knepley 2188e600fa54SMatthew G. Knepley /*@ 218920f4b53cSBarry Smith DMPlexDistributeGetDefault - Get flag indicating whether the `DM` should be distributed by default 2190e600fa54SMatthew G. Knepley 219120f4b53cSBarry Smith Not Collective 2192e600fa54SMatthew G. Knepley 2193e600fa54SMatthew G. Knepley Input Parameter: 219420f4b53cSBarry Smith . dm - The `DM` 2195e600fa54SMatthew G. Knepley 2196e600fa54SMatthew G. Knepley Output Parameter: 2197e600fa54SMatthew G. Knepley . dist - Flag for distribution 2198e600fa54SMatthew G. Knepley 2199e600fa54SMatthew G. Knepley Level: intermediate 2200e600fa54SMatthew G. Knepley 220120f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexDistributeSetDefault()`, `DMPlexDistribute()` 2202e600fa54SMatthew G. Knepley @*/ 2203d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault(DM dm, PetscBool *dist) 2204d71ae5a4SJacob Faibussowitsch { 2205e600fa54SMatthew G. Knepley PetscFunctionBegin; 2206e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22074f572ea9SToby Isaac PetscAssertPointer(dist, 2); 2208cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexDistributeGetDefault_C", (DM, PetscBool *), (dm, dist)); 22093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2210e600fa54SMatthew G. Knepley } 2211e600fa54SMatthew G. Knepley 2212ce78bad3SBarry Smith /*@ 221320f4b53cSBarry Smith DMPlexGetGatherDM - Get a copy of the `DMPLEX` that gathers all points on the 22146462276dSToby Isaac root process of the original's communicator. 22156462276dSToby Isaac 221620f4b53cSBarry Smith Collective 221783655b49SVáclav Hapla 2218064ec1f3Sprj- Input Parameter: 221920f4b53cSBarry Smith . dm - the original `DMPLEX` object 22206462276dSToby Isaac 22216462276dSToby Isaac Output Parameters: 222220f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional) 222320f4b53cSBarry Smith - gatherMesh - the gathered `DM` object, or `NULL` 22246462276dSToby Isaac 22256462276dSToby Isaac Level: intermediate 22266462276dSToby Isaac 222720f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `PetscSF`, `DMPlexDistribute()`, `DMPlexGetRedundantDM()` 22286462276dSToby Isaac @*/ 2229ce78bad3SBarry Smith PetscErrorCode DMPlexGetGatherDM(DM dm, PetscSF *sf, PeOp DM *gatherMesh) 2230d71ae5a4SJacob Faibussowitsch { 22316462276dSToby Isaac MPI_Comm comm; 22326462276dSToby Isaac PetscMPIInt size; 22336462276dSToby Isaac PetscPartitioner oldPart, gatherPart; 22346462276dSToby Isaac 22356462276dSToby Isaac PetscFunctionBegin; 22366462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22374f572ea9SToby Isaac PetscAssertPointer(gatherMesh, 3); 22380c86c063SLisandro Dalcin *gatherMesh = NULL; 2239a13df41bSStefano Zampini if (sf) *sf = NULL; 22406462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 22419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 22423ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 22439566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &oldPart)); 22449566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)oldPart)); 22459566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(comm, &gatherPart)); 22469566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetType(gatherPart, PETSCPARTITIONERGATHER)); 22479566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, gatherPart)); 22489566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, sf, gatherMesh)); 2249a13df41bSStefano Zampini 22509566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, oldPart)); 22519566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&gatherPart)); 22529566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&oldPart)); 22533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22546462276dSToby Isaac } 22556462276dSToby Isaac 2256ce78bad3SBarry Smith /*@ 225720f4b53cSBarry Smith DMPlexGetRedundantDM - Get a copy of the `DMPLEX` that is completely copied on each process. 22586462276dSToby Isaac 225920f4b53cSBarry Smith Collective 226083655b49SVáclav Hapla 2261064ec1f3Sprj- Input Parameter: 226220f4b53cSBarry Smith . dm - the original `DMPLEX` object 22636462276dSToby Isaac 22646462276dSToby Isaac Output Parameters: 226520f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional) 226620f4b53cSBarry Smith - redundantMesh - the redundant `DM` object, or `NULL` 22676462276dSToby Isaac 22686462276dSToby Isaac Level: intermediate 22696462276dSToby Isaac 227060225df5SJacob Faibussowitsch .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetGatherDM()` 22716462276dSToby Isaac @*/ 2272ce78bad3SBarry Smith PetscErrorCode DMPlexGetRedundantDM(DM dm, PetscSF *sf, PeOp DM *redundantMesh) 2273d71ae5a4SJacob Faibussowitsch { 22746462276dSToby Isaac MPI_Comm comm; 22756462276dSToby Isaac PetscMPIInt size, rank; 22766462276dSToby Isaac PetscInt pStart, pEnd, p; 22776462276dSToby Isaac PetscInt numPoints = -1; 2278a13df41bSStefano Zampini PetscSF migrationSF, sfPoint, gatherSF; 22796462276dSToby Isaac DM gatherDM, dmCoord; 22806462276dSToby Isaac PetscSFNode *points; 22816462276dSToby Isaac 22826462276dSToby Isaac PetscFunctionBegin; 22836462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22844f572ea9SToby Isaac PetscAssertPointer(redundantMesh, 3); 22850c86c063SLisandro Dalcin *redundantMesh = NULL; 22866462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 22879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 228868dbc166SMatthew G. Knepley if (size == 1) { 22899566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 229068dbc166SMatthew G. Knepley *redundantMesh = dm; 2291a13df41bSStefano Zampini if (sf) *sf = NULL; 22923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 229368dbc166SMatthew G. Knepley } 22949566063dSJacob Faibussowitsch PetscCall(DMPlexGetGatherDM(dm, &gatherSF, &gatherDM)); 22953ba16761SJacob Faibussowitsch if (!gatherDM) PetscFunctionReturn(PETSC_SUCCESS); 22969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 22979566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(gatherDM, &pStart, &pEnd)); 22986462276dSToby Isaac numPoints = pEnd - pStart; 22999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numPoints, 1, MPIU_INT, 0, comm)); 23009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &points)); 23019566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &migrationSF)); 23026462276dSToby Isaac for (p = 0; p < numPoints; p++) { 23036462276dSToby Isaac points[p].index = p; 23046462276dSToby Isaac points[p].rank = 0; 23056462276dSToby Isaac } 23069566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(migrationSF, pEnd - pStart, numPoints, NULL, PETSC_OWN_POINTER, points, PETSC_OWN_POINTER)); 23079566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, redundantMesh)); 23089566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*redundantMesh, "Redundant Mesh")); 23099566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(gatherDM, migrationSF, *redundantMesh)); 23102e28cf0cSVaclav Hapla /* This is to express that all point are in overlap */ 23111690c2aeSBarry Smith PetscCall(DMPlexSetOverlap_Plex(*redundantMesh, NULL, PETSC_INT_MAX)); 23129566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*redundantMesh, migrationSF, PETSC_FALSE, &sfPoint)); 23139566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*redundantMesh, sfPoint)); 23149566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*redundantMesh, &dmCoord)); 23159566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 23169566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 2317a13df41bSStefano Zampini if (sf) { 2318a13df41bSStefano Zampini PetscSF tsf; 2319a13df41bSStefano Zampini 23209566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(gatherSF, migrationSF, &tsf)); 23219566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, tsf, sf)); 23229566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&tsf)); 2323a13df41bSStefano Zampini } 23249566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&migrationSF)); 23259566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&gatherSF)); 23269566063dSJacob Faibussowitsch PetscCall(DMDestroy(&gatherDM)); 23279566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *redundantMesh)); 23285de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *redundantMesh)); 23293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23306462276dSToby Isaac } 23315fa78c88SVaclav Hapla 23325fa78c88SVaclav Hapla /*@ 233320f4b53cSBarry Smith DMPlexIsDistributed - Find out whether this `DM` is distributed, i.e. more than one rank owns some points. 23345fa78c88SVaclav Hapla 23355fa78c88SVaclav Hapla Collective 23365fa78c88SVaclav Hapla 23375fa78c88SVaclav Hapla Input Parameter: 233820f4b53cSBarry Smith . dm - The `DM` object 23395fa78c88SVaclav Hapla 23405fa78c88SVaclav Hapla Output Parameter: 234120f4b53cSBarry Smith . distributed - Flag whether the `DM` is distributed 23425fa78c88SVaclav Hapla 23435fa78c88SVaclav Hapla Level: intermediate 23445fa78c88SVaclav Hapla 23455fa78c88SVaclav Hapla Notes: 23465fa78c88SVaclav Hapla This currently finds out whether at least two ranks have any DAG points. 234720f4b53cSBarry Smith This involves `MPI_Allreduce()` with one integer. 23485fa78c88SVaclav Hapla The result is currently not stashed so every call to this routine involves this global communication. 23495fa78c88SVaclav Hapla 235060225df5SJacob Faibussowitsch .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetOverlap()`, `DMPlexIsInterpolated()` 23515fa78c88SVaclav Hapla @*/ 2352d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsDistributed(DM dm, PetscBool *distributed) 2353d71ae5a4SJacob Faibussowitsch { 23545fa78c88SVaclav Hapla PetscInt pStart, pEnd, count; 23555fa78c88SVaclav Hapla MPI_Comm comm; 235635d70e31SStefano Zampini PetscMPIInt size; 23575fa78c88SVaclav Hapla 23585fa78c88SVaclav Hapla PetscFunctionBegin; 23595fa78c88SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23604f572ea9SToby Isaac PetscAssertPointer(distributed, 2); 23619566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 23629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 23639371c9d4SSatish Balay if (size == 1) { 23649371c9d4SSatish Balay *distributed = PETSC_FALSE; 23653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23669371c9d4SSatish Balay } 23679566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 236835d70e31SStefano Zampini count = (pEnd - pStart) > 0 ? 1 : 0; 2369462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &count, 1, MPIU_INT, MPI_SUM, comm)); 23705fa78c88SVaclav Hapla *distributed = count > 1 ? PETSC_TRUE : PETSC_FALSE; 23713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23725fa78c88SVaclav Hapla } 23731d1f2f2aSksagiyam 2374cc4c1da9SBarry Smith /*@ 23751d1f2f2aSksagiyam DMPlexDistributionSetName - Set the name of the specific parallel distribution 23761d1f2f2aSksagiyam 23771d1f2f2aSksagiyam Input Parameters: 237820f4b53cSBarry Smith + dm - The `DM` 23791d1f2f2aSksagiyam - name - The name of the specific parallel distribution 23801d1f2f2aSksagiyam 23811d1f2f2aSksagiyam Level: developer 23821d1f2f2aSksagiyam 238320f4b53cSBarry Smith Note: 238420f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's 238520f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under 238620f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()` 238720f4b53cSBarry Smith loads the parallel distribution stored in file under this name. 238820f4b53cSBarry Smith 238920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionGetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()` 23901d1f2f2aSksagiyam @*/ 2391d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionSetName(DM dm, const char name[]) 2392d71ae5a4SJacob Faibussowitsch { 23931d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data; 23941d1f2f2aSksagiyam 23951d1f2f2aSksagiyam PetscFunctionBegin; 23961d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 23974f572ea9SToby Isaac if (name) PetscAssertPointer(name, 2); 23981d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 23991d1f2f2aSksagiyam PetscCall(PetscStrallocpy(name, &mesh->distributionName)); 24003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24011d1f2f2aSksagiyam } 24021d1f2f2aSksagiyam 2403cc4c1da9SBarry Smith /*@ 24041d1f2f2aSksagiyam DMPlexDistributionGetName - Retrieve the name of the specific parallel distribution 24051d1f2f2aSksagiyam 24061d1f2f2aSksagiyam Input Parameter: 240720f4b53cSBarry Smith . dm - The `DM` 24081d1f2f2aSksagiyam 24091d1f2f2aSksagiyam Output Parameter: 24101d1f2f2aSksagiyam . name - The name of the specific parallel distribution 24111d1f2f2aSksagiyam 24121d1f2f2aSksagiyam Level: developer 24131d1f2f2aSksagiyam 241420f4b53cSBarry Smith Note: 241520f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's 241620f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under 241720f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()` 241820f4b53cSBarry Smith loads the parallel distribution stored in file under this name. 241920f4b53cSBarry Smith 242020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionSetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()` 24211d1f2f2aSksagiyam @*/ 2422d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionGetName(DM dm, const char *name[]) 2423d71ae5a4SJacob Faibussowitsch { 24241d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data; 24251d1f2f2aSksagiyam 24261d1f2f2aSksagiyam PetscFunctionBegin; 24271d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 24284f572ea9SToby Isaac PetscAssertPointer(name, 2); 24291d1f2f2aSksagiyam *name = mesh->distributionName; 24303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24311d1f2f2aSksagiyam } 2432