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 179d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAdjacency_Internal(DM dm, PetscInt p, PetscBool useCone, PetscBool useTransitiveClosure, PetscBool useAnchors, PetscInt *adjSize, PetscInt *adj[]) 180d71ae5a4SJacob Faibussowitsch { 18179bad331SMatthew G. Knepley static PetscInt asiz = 0; 1828b0b4c70SToby Isaac PetscInt maxAnchors = 1; 1838b0b4c70SToby Isaac PetscInt aStart = -1, aEnd = -1; 1848b0b4c70SToby Isaac PetscInt maxAdjSize; 1858b0b4c70SToby Isaac PetscSection aSec = NULL; 1868b0b4c70SToby Isaac IS aIS = NULL; 1878b0b4c70SToby Isaac const PetscInt *anchors; 1883c1f0c11SLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 18970034214SMatthew G. Knepley 19070034214SMatthew G. Knepley PetscFunctionBeginHot; 1915b317d89SToby Isaac if (useAnchors) { 1929566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 1938b0b4c70SToby Isaac if (aSec) { 1949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchors)); 19524c766afSToby Isaac maxAnchors = PetscMax(1, maxAnchors); 1969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 1979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 1988b0b4c70SToby Isaac } 1998b0b4c70SToby Isaac } 20079bad331SMatthew G. Knepley if (!*adj) { 201cf910586SMatthew G. Knepley PetscInt depth, maxC, maxS, maxP, pStart, pEnd; 20279bad331SMatthew G. Knepley 2039566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 2049566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 205412e9a14SMatthew G. Knepley depth = PetscMax(depth, -depth); 2069566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxC, &maxS)); 207cf910586SMatthew G. Knepley maxP = maxS * maxC; 208cf910586SMatthew G. Knepley /* Adjacency can be as large as supp(cl(cell)) or cl(supp(vertex)), 209cf910586SMatthew G. Knepley supp(cell) + supp(maxC faces) + supp(maxC^2 edges) + supp(maxC^3 vertices) 210cf910586SMatthew G. Knepley = 0 + maxS*maxC + maxS^2*maxC^2 + maxS^3*maxC^3 211cf910586SMatthew G. Knepley = \sum^d_{i=0} (maxS*maxC)^i - 1 212cf910586SMatthew G. Knepley = (maxS*maxC)^{d+1} - 1 / (maxS*maxC - 1) - 1 213cf910586SMatthew G. Knepley We could improve this by getting the max by strata: 214cf910586SMatthew 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) 215cf910586SMatthew 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] 216cf910586SMatthew G. Knepley and the same with S and C reversed 217cf910586SMatthew G. Knepley */ 218cf910586SMatthew G. Knepley if ((depth == 3 && maxP > 200) || (depth == 2 && maxP > 580)) asiz = pEnd - pStart; 219cf910586SMatthew G. Knepley else asiz = (maxP > 1) ? ((PetscPowInt(maxP, depth + 1) - 1) / (maxP - 1)) : depth + 1; 2208b0b4c70SToby Isaac asiz *= maxAnchors; 22124c766afSToby Isaac asiz = PetscMin(asiz, pEnd - pStart); 2229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(asiz, adj)); 22379bad331SMatthew G. Knepley } 22479bad331SMatthew G. Knepley if (*adjSize < 0) *adjSize = asiz; 2258b0b4c70SToby Isaac maxAdjSize = *adjSize; 2263c1f0c11SLawrence Mitchell if (mesh->useradjacency) { 2279566063dSJacob Faibussowitsch PetscCall((*mesh->useradjacency)(dm, p, adjSize, *adj, mesh->useradjacencyctx)); 2283c1f0c11SLawrence Mitchell } else if (useTransitiveClosure) { 2299566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Transitive_Internal(dm, p, useCone, adjSize, *adj)); 23070034214SMatthew G. Knepley } else if (useCone) { 2319566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Cone_Internal(dm, p, adjSize, *adj)); 23270034214SMatthew G. Knepley } else { 2339566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Support_Internal(dm, p, adjSize, *adj)); 23470034214SMatthew G. Knepley } 2355b317d89SToby Isaac if (useAnchors && aSec) { 2368b0b4c70SToby Isaac PetscInt origSize = *adjSize; 2378b0b4c70SToby Isaac PetscInt numAdj = origSize; 2388b0b4c70SToby Isaac PetscInt i = 0, j; 2398b0b4c70SToby Isaac PetscInt *orig = *adj; 2408b0b4c70SToby Isaac 2418b0b4c70SToby Isaac while (i < origSize) { 2428b0b4c70SToby Isaac PetscInt p = orig[i]; 2438b0b4c70SToby Isaac PetscInt aDof = 0; 2448b0b4c70SToby Isaac 24548a46eb9SPierre Jolivet if (p >= aStart && p < aEnd) PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 2468b0b4c70SToby Isaac if (aDof) { 2478b0b4c70SToby Isaac PetscInt aOff; 2488b0b4c70SToby Isaac PetscInt s, q; 2498b0b4c70SToby Isaac 250ad540459SPierre Jolivet for (j = i + 1; j < numAdj; j++) orig[j - 1] = orig[j]; 2518b0b4c70SToby Isaac origSize--; 2528b0b4c70SToby Isaac numAdj--; 2539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 2548b0b4c70SToby Isaac for (s = 0; s < aDof; ++s) { 255527e7439SSatish Balay for (q = 0; q < numAdj || ((void)(orig[numAdj++] = anchors[aOff + s]), 0); ++q) { 2568b0b4c70SToby Isaac if (anchors[aOff + s] == orig[q]) break; 2578b0b4c70SToby Isaac } 25863a3b9bcSJacob Faibussowitsch PetscCheck(numAdj <= maxAdjSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%" PetscInt_FMT ")", maxAdjSize); 2598b0b4c70SToby Isaac } 2609371c9d4SSatish Balay } else { 2618b0b4c70SToby Isaac i++; 2628b0b4c70SToby Isaac } 2638b0b4c70SToby Isaac } 2648b0b4c70SToby Isaac *adjSize = numAdj; 2659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 2668b0b4c70SToby Isaac } 2673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26870034214SMatthew G. Knepley } 26970034214SMatthew G. Knepley 27070034214SMatthew G. Knepley /*@ 27170034214SMatthew G. Knepley DMPlexGetAdjacency - Return all points adjacent to the given point 27270034214SMatthew G. Knepley 27370034214SMatthew G. Knepley Input Parameters: 27420f4b53cSBarry Smith + dm - The `DM` object 2756b867d5aSJose E. Roman - p - The point 27670034214SMatthew G. Knepley 2776b867d5aSJose E. Roman Input/Output Parameters: 27820f4b53cSBarry Smith + adjSize - The maximum size of `adj` if it is non-`NULL`, or `PETSC_DETERMINE`; 2796b867d5aSJose E. Roman on output the number of adjacent points 28020f4b53cSBarry Smith - adj - Either `NULL` so that the array is allocated, or an existing array with size `adjSize`; 2816b867d5aSJose E. Roman on output contains the adjacent points 28270034214SMatthew G. Knepley 28370034214SMatthew G. Knepley Level: advanced 28470034214SMatthew G. Knepley 28595452b02SPatrick Sanan Notes: 28620f4b53cSBarry Smith The user must `PetscFree()` the `adj` array if it was not passed in. 28770034214SMatthew G. Knepley 28820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMCreateMatrix()`, `DMPlexPreallocateOperator()` 28970034214SMatthew G. Knepley @*/ 290d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAdjacency(DM dm, PetscInt p, PetscInt *adjSize, PetscInt *adj[]) 291d71ae5a4SJacob Faibussowitsch { 2921cf84007SMatthew G. Knepley PetscBool useCone, useClosure, useAnchors; 29370034214SMatthew G. Knepley 29470034214SMatthew G. Knepley PetscFunctionBeginHot; 29570034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2964f572ea9SToby Isaac PetscAssertPointer(adjSize, 3); 2974f572ea9SToby Isaac PetscAssertPointer(adj, 4); 2989566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 2999566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors)); 3009566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, adjSize, adj)); 3013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30270034214SMatthew G. Knepley } 30308633170SToby Isaac 304b0a623aaSMatthew G. Knepley /*@ 30520f4b53cSBarry Smith DMPlexCreateTwoSidedProcessSF - Create an `PetscSF` which just has process connectivity 306b0a623aaSMatthew G. Knepley 30720f4b53cSBarry Smith Collective 308b0a623aaSMatthew G. Knepley 309b0a623aaSMatthew G. Knepley Input Parameters: 31020f4b53cSBarry Smith + dm - The `DM` 31120f4b53cSBarry Smith . sfPoint - The `PetscSF` which encodes point connectivity 31220f4b53cSBarry Smith . rootRankSection - to be documented 31320f4b53cSBarry Smith . rootRanks - to be documented 31460225df5SJacob Faibussowitsch . leafRankSection - to be documented 31520f4b53cSBarry Smith - leafRanks - to be documented 316b0a623aaSMatthew G. Knepley 317b0a623aaSMatthew G. Knepley Output Parameters: 31820f4b53cSBarry Smith + processRanks - A list of process neighbors, or `NULL` 31920f4b53cSBarry Smith - sfProcess - An `PetscSF` encoding the two-sided process connectivity, or `NULL` 320b0a623aaSMatthew G. Knepley 321b0a623aaSMatthew G. Knepley Level: developer 322b0a623aaSMatthew G. Knepley 32320f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSFCreate()`, `DMPlexCreateProcessSF()` 324b0a623aaSMatthew G. Knepley @*/ 325d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateTwoSidedProcessSF(DM dm, PetscSF sfPoint, PetscSection rootRankSection, IS rootRanks, PetscSection leafRankSection, IS leafRanks, IS *processRanks, PetscSF *sfProcess) 326d71ae5a4SJacob Faibussowitsch { 327b0a623aaSMatthew G. Knepley const PetscSFNode *remotePoints; 328b0a623aaSMatthew G. Knepley PetscInt *localPointsNew; 329b0a623aaSMatthew G. Knepley PetscSFNode *remotePointsNew; 330b0a623aaSMatthew G. Knepley const PetscInt *nranks; 331b0a623aaSMatthew G. Knepley PetscInt *ranksNew; 332b0a623aaSMatthew G. Knepley PetscBT neighbors; 333b0a623aaSMatthew G. Knepley PetscInt pStart, pEnd, p, numLeaves, l, numNeighbors, n; 3349852e123SBarry Smith PetscMPIInt size, proc, rank; 335b0a623aaSMatthew G. Knepley 336b0a623aaSMatthew G. Knepley PetscFunctionBegin; 337b0a623aaSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 338b0a623aaSMatthew G. Knepley PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2); 3394f572ea9SToby Isaac if (processRanks) PetscAssertPointer(processRanks, 7); 3404f572ea9SToby Isaac if (sfProcess) PetscAssertPointer(sfProcess, 8); 3419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 3429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 3439566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &numLeaves, NULL, &remotePoints)); 3449566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(size, &neighbors)); 3459566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(size, neighbors)); 346b0a623aaSMatthew G. Knepley /* Compute root-to-leaf process connectivity */ 3479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(rootRankSection, &pStart, &pEnd)); 3489566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rootRanks, &nranks)); 349b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 350b0a623aaSMatthew G. Knepley PetscInt ndof, noff, n; 351b0a623aaSMatthew G. Knepley 3529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootRankSection, p, &ndof)); 3539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootRankSection, p, &noff)); 3549566063dSJacob Faibussowitsch for (n = 0; n < ndof; ++n) PetscCall(PetscBTSet(neighbors, nranks[noff + n])); 355b0a623aaSMatthew G. Knepley } 3569566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rootRanks, &nranks)); 357b0a623aaSMatthew G. Knepley /* Compute leaf-to-neighbor process connectivity */ 3589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafRankSection, &pStart, &pEnd)); 3599566063dSJacob Faibussowitsch PetscCall(ISGetIndices(leafRanks, &nranks)); 360b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 361b0a623aaSMatthew G. Knepley PetscInt ndof, noff, n; 362b0a623aaSMatthew G. Knepley 3639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafRankSection, p, &ndof)); 3649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafRankSection, p, &noff)); 3659566063dSJacob Faibussowitsch for (n = 0; n < ndof; ++n) PetscCall(PetscBTSet(neighbors, nranks[noff + n])); 366b0a623aaSMatthew G. Knepley } 3679566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(leafRanks, &nranks)); 368b0a623aaSMatthew G. Knepley /* Compute leaf-to-root process connectivity */ 3693ba16761SJacob Faibussowitsch for (l = 0; l < numLeaves; ++l) PetscCall(PetscBTSet(neighbors, remotePoints[l].rank)); 370b0a623aaSMatthew G. Knepley /* Calculate edges */ 3713ba16761SJacob Faibussowitsch PetscCall(PetscBTClear(neighbors, rank)); 3729371c9d4SSatish Balay for (proc = 0, numNeighbors = 0; proc < size; ++proc) { 3739371c9d4SSatish Balay if (PetscBTLookup(neighbors, proc)) ++numNeighbors; 3749371c9d4SSatish Balay } 3759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNeighbors, &ranksNew)); 3769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNeighbors, &localPointsNew)); 3779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNeighbors, &remotePointsNew)); 3789852e123SBarry Smith for (proc = 0, n = 0; proc < size; ++proc) { 379b0a623aaSMatthew G. Knepley if (PetscBTLookup(neighbors, proc)) { 380b0a623aaSMatthew G. Knepley ranksNew[n] = proc; 381b0a623aaSMatthew G. Knepley localPointsNew[n] = proc; 382b0a623aaSMatthew G. Knepley remotePointsNew[n].index = rank; 383b0a623aaSMatthew G. Knepley remotePointsNew[n].rank = proc; 384b0a623aaSMatthew G. Knepley ++n; 385b0a623aaSMatthew G. Knepley } 386b0a623aaSMatthew G. Knepley } 3879566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&neighbors)); 3889566063dSJacob Faibussowitsch if (processRanks) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), numNeighbors, ranksNew, PETSC_OWN_POINTER, processRanks)); 3899566063dSJacob Faibussowitsch else PetscCall(PetscFree(ranksNew)); 390b0a623aaSMatthew G. Knepley if (sfProcess) { 3919566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess)); 3929566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*sfProcess, "Two-Sided Process SF")); 3939566063dSJacob Faibussowitsch PetscCall(PetscSFSetFromOptions(*sfProcess)); 3949566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sfProcess, size, numNeighbors, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER)); 395b0a623aaSMatthew G. Knepley } 3963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 397b0a623aaSMatthew G. Knepley } 398b0a623aaSMatthew G. Knepley 399b0a623aaSMatthew G. Knepley /*@ 400b0a623aaSMatthew G. Knepley DMPlexDistributeOwnership - Compute owner information for shared points. This basically gets two-sided for an SF. 401b0a623aaSMatthew G. Knepley 40220f4b53cSBarry Smith Collective 403b0a623aaSMatthew G. Knepley 404b0a623aaSMatthew G. Knepley Input Parameter: 40520f4b53cSBarry Smith . dm - The `DM` 406b0a623aaSMatthew G. Knepley 407b0a623aaSMatthew G. Knepley Output Parameters: 408b0a623aaSMatthew G. Knepley + rootSection - The number of leaves for a given root point 409b0a623aaSMatthew G. Knepley . rootrank - The rank of each edge into the root point 410b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point 411b0a623aaSMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point 412b0a623aaSMatthew G. Knepley 413b0a623aaSMatthew G. Knepley Level: developer 414b0a623aaSMatthew G. Knepley 41520f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabel()`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 416b0a623aaSMatthew G. Knepley @*/ 417d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeOwnership(DM dm, PetscSection rootSection, IS *rootrank, PetscSection leafSection, IS *leafrank) 418d71ae5a4SJacob Faibussowitsch { 419b0a623aaSMatthew G. Knepley MPI_Comm comm; 420b0a623aaSMatthew G. Knepley PetscSF sfPoint; 421b0a623aaSMatthew G. Knepley const PetscInt *rootdegree; 422b0a623aaSMatthew G. Knepley PetscInt *myrank, *remoterank; 423b0a623aaSMatthew G. Knepley PetscInt pStart, pEnd, p, nedges; 424b0a623aaSMatthew G. Knepley PetscMPIInt rank; 425b0a623aaSMatthew G. Knepley 426b0a623aaSMatthew G. Knepley PetscFunctionBegin; 4279566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 4299566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4309566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 431b0a623aaSMatthew G. Knepley /* Compute number of leaves for each root */ 4329566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rootSection, "Root Section")); 4339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection, pStart, pEnd)); 4349566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sfPoint, &rootdegree)); 4359566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sfPoint, &rootdegree)); 4369566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(rootSection, p, rootdegree[p - pStart])); 4379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection)); 438b0a623aaSMatthew G. Knepley /* Gather rank of each leaf to root */ 4399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &nedges)); 4409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &myrank)); 4419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nedges, &remoterank)); 442b0a623aaSMatthew G. Knepley for (p = 0; p < pEnd - pStart; ++p) myrank[p] = rank; 4439566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sfPoint, MPIU_INT, myrank, remoterank)); 4449566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sfPoint, MPIU_INT, myrank, remoterank)); 4459566063dSJacob Faibussowitsch PetscCall(PetscFree(myrank)); 4469566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, nedges, remoterank, PETSC_OWN_POINTER, rootrank)); 447b0a623aaSMatthew G. Knepley /* Distribute remote ranks to leaves */ 4489566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)leafSection, "Leaf Section")); 4499566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeFieldIS(dm, sfPoint, rootSection, *rootrank, leafSection, leafrank)); 4503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 451b0a623aaSMatthew G. Knepley } 452b0a623aaSMatthew G. Knepley 453278397a0SMatthew G. Knepley /*@C 454c506a872SMatthew G. Knepley DMPlexCreateOverlapLabel - Compute a label indicating what overlap points should be sent to new processes 455b0a623aaSMatthew G. Knepley 45620f4b53cSBarry Smith Collective 457b0a623aaSMatthew G. Knepley 458b0a623aaSMatthew G. Knepley Input Parameters: 45920f4b53cSBarry Smith + dm - The `DM` 46024d039d7SMichael Lange . levels - Number of overlap levels 461b0a623aaSMatthew G. Knepley . rootSection - The number of leaves for a given root point 462b0a623aaSMatthew G. Knepley . rootrank - The rank of each edge into the root point 463b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point 464b0a623aaSMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point 465b0a623aaSMatthew G. Knepley 466064ec1f3Sprj- Output Parameter: 46720f4b53cSBarry Smith . ovLabel - `DMLabel` containing remote overlap contributions as point/rank pairings 468b0a623aaSMatthew G. Knepley 469b0a623aaSMatthew G. Knepley Level: developer 470b0a623aaSMatthew G. Knepley 47120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabelFromLabels()`, `DMPlexGetAdjacency()`, `DMPlexDistributeOwnership()`, `DMPlexDistribute()` 472b0a623aaSMatthew G. Knepley @*/ 473d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateOverlapLabel(DM dm, PetscInt levels, PetscSection rootSection, IS rootrank, PetscSection leafSection, IS leafrank, DMLabel *ovLabel) 474d71ae5a4SJacob Faibussowitsch { 475e540f424SMichael Lange MPI_Comm comm; 476b0a623aaSMatthew G. Knepley DMLabel ovAdjByRank; /* A DMLabel containing all points adjacent to shared points, separated by rank (value in label) */ 477874ddda9SLisandro Dalcin PetscSF sfPoint; 478b0a623aaSMatthew G. Knepley const PetscSFNode *remote; 479b0a623aaSMatthew G. Knepley const PetscInt *local; 4801fd9873aSMichael Lange const PetscInt *nrank, *rrank; 481b0a623aaSMatthew G. Knepley PetscInt *adj = NULL; 4821fd9873aSMichael Lange PetscInt pStart, pEnd, p, sStart, sEnd, nleaves, l; 4839852e123SBarry Smith PetscMPIInt rank, size; 48431bc6364SLisandro Dalcin PetscBool flg; 485b0a623aaSMatthew G. Knepley 486b0a623aaSMatthew G. Knepley PetscFunctionBegin; 4876ba1a4c7SVaclav Hapla *ovLabel = NULL; 4889566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 4909566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 4913ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 4929566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 4939566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 494d1674c6dSMatthew Knepley if (!levels) { 495d1674c6dSMatthew Knepley /* Add owned points */ 4969566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel)); 4979566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) PetscCall(DMLabelSetValue(*ovLabel, p, rank)); 4983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 499d1674c6dSMatthew Knepley } 5009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafSection, &sStart, &sEnd)); 5019566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote)); 5029566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap adjacency", &ovAdjByRank)); 503b0a623aaSMatthew G. Knepley /* Handle leaves: shared with the root point */ 504b0a623aaSMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 505b0a623aaSMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a; 506b0a623aaSMatthew G. Knepley 5079566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, local ? local[l] : l, &adjSize, &adj)); 5089566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remote[l].rank)); 509b0a623aaSMatthew G. Knepley } 5109566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rootrank, &rrank)); 5119566063dSJacob Faibussowitsch PetscCall(ISGetIndices(leafrank, &nrank)); 512b0a623aaSMatthew G. Knepley /* Handle roots */ 513b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 514b0a623aaSMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, neighbors = 0, noff, n, a; 515b0a623aaSMatthew G. Knepley 516b0a623aaSMatthew G. Knepley if ((p >= sStart) && (p < sEnd)) { 517b0a623aaSMatthew G. Knepley /* Some leaves share a root with other leaves on different processes */ 5189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, p, &neighbors)); 519b0a623aaSMatthew G. Knepley if (neighbors) { 5209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafSection, p, &noff)); 5219566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 522b0a623aaSMatthew G. Knepley for (n = 0; n < neighbors; ++n) { 523b0a623aaSMatthew G. Knepley const PetscInt remoteRank = nrank[noff + n]; 524b0a623aaSMatthew G. Knepley 525b0a623aaSMatthew G. Knepley if (remoteRank == rank) continue; 5269566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 527b0a623aaSMatthew G. Knepley } 528b0a623aaSMatthew G. Knepley } 529b0a623aaSMatthew G. Knepley } 530b0a623aaSMatthew G. Knepley /* Roots are shared with leaves */ 5319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSection, p, &neighbors)); 532b0a623aaSMatthew G. Knepley if (!neighbors) continue; 5339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, p, &noff)); 5349566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 535b0a623aaSMatthew G. Knepley for (n = 0; n < neighbors; ++n) { 536b0a623aaSMatthew G. Knepley const PetscInt remoteRank = rrank[noff + n]; 537b0a623aaSMatthew G. Knepley 538b0a623aaSMatthew G. Knepley if (remoteRank == rank) continue; 5399566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 540b0a623aaSMatthew G. Knepley } 541b0a623aaSMatthew G. Knepley } 5429566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 5439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rootrank, &rrank)); 5449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(leafrank, &nrank)); 54524d039d7SMichael Lange /* Add additional overlap levels */ 546be200f8dSMichael Lange for (l = 1; l < levels; l++) { 547be200f8dSMichael Lange /* Propagate point donations over SF to capture remote connections */ 5489566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelPropagate(dm, ovAdjByRank)); 549be200f8dSMichael Lange /* Add next level of point donations to the label */ 5509566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelAdjacency(dm, ovAdjByRank)); 551be200f8dSMichael Lange } 55226a7d390SMatthew G. Knepley /* We require the closure in the overlap */ 5539566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelClosure(dm, ovAdjByRank)); 5549566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-overlap_view", &flg)); 555e540f424SMichael Lange if (flg) { 556825f8a23SLisandro Dalcin PetscViewer viewer; 5579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &viewer)); 5589566063dSJacob Faibussowitsch PetscCall(DMLabelView(ovAdjByRank, viewer)); 559b0a623aaSMatthew G. Knepley } 560874ddda9SLisandro Dalcin /* Invert sender to receiver label */ 5619566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel)); 5629566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelInvert(dm, ovAdjByRank, NULL, *ovLabel)); 563a9f1d5b2SMichael Lange /* Add owned points, except for shared local points */ 5649566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) PetscCall(DMLabelSetValue(*ovLabel, p, rank)); 565e540f424SMichael Lange for (l = 0; l < nleaves; ++l) { 5669566063dSJacob Faibussowitsch PetscCall(DMLabelClearValue(*ovLabel, local[l], rank)); 5679566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(*ovLabel, remote[l].index, remote[l].rank)); 568e540f424SMichael Lange } 569e540f424SMichael Lange /* Clean up */ 5709566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&ovAdjByRank)); 5713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 572b0a623aaSMatthew G. Knepley } 57370034214SMatthew G. Knepley 574d71ae5a4SJacob Faibussowitsch static PetscErrorCode HandlePoint_Private(DM dm, PetscInt p, PetscSection section, const PetscInt ranks[], PetscInt numExLabels, const DMLabel exLabel[], const PetscInt exValue[], DMLabel ovAdjByRank) 575d71ae5a4SJacob Faibussowitsch { 576c506a872SMatthew G. Knepley PetscInt neighbors, el; 577c506a872SMatthew G. Knepley 578c506a872SMatthew G. Knepley PetscFunctionBegin; 579c506a872SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, p, &neighbors)); 580c506a872SMatthew G. Knepley if (neighbors) { 581c506a872SMatthew G. Knepley PetscInt *adj = NULL; 582c506a872SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, noff, n, a; 583c506a872SMatthew G. Knepley PetscMPIInt rank; 584c506a872SMatthew G. Knepley 585c506a872SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 586c506a872SMatthew G. Knepley PetscCall(PetscSectionGetOffset(section, p, &noff)); 587c506a872SMatthew G. Knepley PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 588c506a872SMatthew G. Knepley for (n = 0; n < neighbors; ++n) { 589c506a872SMatthew G. Knepley const PetscInt remoteRank = ranks[noff + n]; 590c506a872SMatthew G. Knepley 591c506a872SMatthew G. Knepley if (remoteRank == rank) continue; 592c506a872SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 593c506a872SMatthew G. Knepley PetscBool insert = PETSC_TRUE; 594c506a872SMatthew G. Knepley 595c506a872SMatthew G. Knepley for (el = 0; el < numExLabels; ++el) { 596c506a872SMatthew G. Knepley PetscInt exVal; 597c506a872SMatthew G. Knepley PetscCall(DMLabelGetValue(exLabel[el], adj[a], &exVal)); 5989371c9d4SSatish Balay if (exVal == exValue[el]) { 5999371c9d4SSatish Balay insert = PETSC_FALSE; 6009371c9d4SSatish Balay break; 6019371c9d4SSatish Balay } 602c506a872SMatthew G. Knepley } 603c506a872SMatthew G. Knepley if (insert) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 604c506a872SMatthew G. Knepley } 605c506a872SMatthew G. Knepley } 606f88a03deSMatthew G. Knepley PetscCall(PetscFree(adj)); 607c506a872SMatthew G. Knepley } 6083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 609c506a872SMatthew G. Knepley } 610c506a872SMatthew G. Knepley 611c506a872SMatthew G. Knepley /*@C 612c506a872SMatthew G. Knepley DMPlexCreateOverlapLabelFromLabels - Compute a label indicating what overlap points should be sent to new processes 613c506a872SMatthew G. Knepley 61420f4b53cSBarry Smith Collective 615c506a872SMatthew G. Knepley 616c506a872SMatthew G. Knepley Input Parameters: 61720f4b53cSBarry Smith + dm - The `DM` 618c506a872SMatthew G. Knepley . numLabels - The number of labels to draw candidate points from 619c506a872SMatthew G. Knepley . label - An array of labels containing candidate points 620c506a872SMatthew G. Knepley . value - An array of label values marking the candidate points 621c506a872SMatthew G. Knepley . numExLabels - The number of labels to use for exclusion 62220f4b53cSBarry Smith . exLabel - An array of labels indicating points to be excluded, or `NULL` 62320f4b53cSBarry Smith . exValue - An array of label values to be excluded, or `NULL` 624c506a872SMatthew G. Knepley . rootSection - The number of leaves for a given root point 625c506a872SMatthew G. Knepley . rootrank - The rank of each edge into the root point 626c506a872SMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point 627c506a872SMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point 628c506a872SMatthew G. Knepley 629c506a872SMatthew G. Knepley Output Parameter: 63020f4b53cSBarry Smith . ovLabel - `DMLabel` containing remote overlap contributions as point/rank pairings 63120f4b53cSBarry Smith 63220f4b53cSBarry Smith Level: developer 633c506a872SMatthew G. Knepley 634c506a872SMatthew G. Knepley Note: 635c506a872SMatthew G. Knepley The candidate points are only added to the overlap if they are adjacent to a shared point 636c506a872SMatthew G. Knepley 63720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabel()`, `DMPlexGetAdjacency()`, `DMPlexDistributeOwnership()`, `DMPlexDistribute()` 638c506a872SMatthew G. Knepley @*/ 639d71ae5a4SJacob 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) 640d71ae5a4SJacob Faibussowitsch { 641c506a872SMatthew G. Knepley MPI_Comm comm; 642c506a872SMatthew G. Knepley DMLabel ovAdjByRank; /* A DMLabel containing all points adjacent to shared points, separated by rank (value in label) */ 643c506a872SMatthew G. Knepley PetscSF sfPoint; 644c506a872SMatthew G. Knepley const PetscSFNode *remote; 645c506a872SMatthew G. Knepley const PetscInt *local; 646c506a872SMatthew G. Knepley const PetscInt *nrank, *rrank; 647c506a872SMatthew G. Knepley PetscInt *adj = NULL; 648c506a872SMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, nleaves, l, el; 649c506a872SMatthew G. Knepley PetscMPIInt rank, size; 650c506a872SMatthew G. Knepley PetscBool flg; 651c506a872SMatthew G. Knepley 652c506a872SMatthew G. Knepley PetscFunctionBegin; 653c506a872SMatthew G. Knepley *ovLabel = NULL; 654c506a872SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 655c506a872SMatthew G. Knepley PetscCallMPI(MPI_Comm_size(comm, &size)); 656c506a872SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 6573ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 658c506a872SMatthew G. Knepley PetscCall(DMGetPointSF(dm, &sfPoint)); 659c506a872SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 660c506a872SMatthew G. Knepley PetscCall(PetscSectionGetChart(leafSection, &sStart, &sEnd)); 661c506a872SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote)); 662c506a872SMatthew G. Knepley PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap adjacency", &ovAdjByRank)); 663c506a872SMatthew G. Knepley PetscCall(ISGetIndices(rootrank, &rrank)); 664c506a872SMatthew G. Knepley PetscCall(ISGetIndices(leafrank, &nrank)); 665c506a872SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 666c506a872SMatthew G. Knepley IS valIS; 667c506a872SMatthew G. Knepley const PetscInt *points; 668c506a872SMatthew G. Knepley PetscInt n; 669c506a872SMatthew G. Knepley 670c506a872SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label[l], value[l], &valIS)); 671c506a872SMatthew G. Knepley if (!valIS) continue; 672c506a872SMatthew G. Knepley PetscCall(ISGetIndices(valIS, &points)); 673c506a872SMatthew G. Knepley PetscCall(ISGetLocalSize(valIS, &n)); 674c506a872SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) { 675c506a872SMatthew G. Knepley const PetscInt p = points[i]; 676c506a872SMatthew G. Knepley 677c506a872SMatthew G. Knepley if ((p >= sStart) && (p < sEnd)) { 678c506a872SMatthew G. Knepley PetscInt loc, adjSize = PETSC_DETERMINE; 679c506a872SMatthew G. Knepley 680c506a872SMatthew G. Knepley /* Handle leaves: shared with the root point */ 681c506a872SMatthew G. Knepley if (local) PetscCall(PetscFindInt(p, nleaves, local, &loc)); 682c506a872SMatthew G. Knepley else loc = (p >= 0 && p < nleaves) ? p : -1; 683c506a872SMatthew G. Knepley if (loc >= 0) { 684c506a872SMatthew G. Knepley const PetscInt remoteRank = remote[loc].rank; 685c506a872SMatthew G. Knepley 686c506a872SMatthew G. Knepley PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 687c506a872SMatthew G. Knepley for (PetscInt a = 0; a < adjSize; ++a) { 688c506a872SMatthew G. Knepley PetscBool insert = PETSC_TRUE; 689c506a872SMatthew G. Knepley 690c506a872SMatthew G. Knepley for (el = 0; el < numExLabels; ++el) { 691c506a872SMatthew G. Knepley PetscInt exVal; 692c506a872SMatthew G. Knepley PetscCall(DMLabelGetValue(exLabel[el], adj[a], &exVal)); 6939371c9d4SSatish Balay if (exVal == exValue[el]) { 6949371c9d4SSatish Balay insert = PETSC_FALSE; 6959371c9d4SSatish Balay break; 6969371c9d4SSatish Balay } 697c506a872SMatthew G. Knepley } 698c506a872SMatthew G. Knepley if (insert) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 699c506a872SMatthew G. Knepley } 700c506a872SMatthew G. Knepley } 701c506a872SMatthew G. Knepley /* Some leaves share a root with other leaves on different processes */ 7023ba16761SJacob Faibussowitsch PetscCall(HandlePoint_Private(dm, p, leafSection, nrank, numExLabels, exLabel, exValue, ovAdjByRank)); 703c506a872SMatthew G. Knepley } 704c506a872SMatthew G. Knepley /* Roots are shared with leaves */ 7053ba16761SJacob Faibussowitsch PetscCall(HandlePoint_Private(dm, p, rootSection, rrank, numExLabels, exLabel, exValue, ovAdjByRank)); 706c506a872SMatthew G. Knepley } 707c506a872SMatthew G. Knepley PetscCall(ISRestoreIndices(valIS, &points)); 708c506a872SMatthew G. Knepley PetscCall(ISDestroy(&valIS)); 709c506a872SMatthew G. Knepley } 710c506a872SMatthew G. Knepley PetscCall(PetscFree(adj)); 711c506a872SMatthew G. Knepley PetscCall(ISRestoreIndices(rootrank, &rrank)); 712c506a872SMatthew G. Knepley PetscCall(ISRestoreIndices(leafrank, &nrank)); 713c506a872SMatthew G. Knepley /* We require the closure in the overlap */ 714c506a872SMatthew G. Knepley PetscCall(DMPlexPartitionLabelClosure(dm, ovAdjByRank)); 715c506a872SMatthew G. Knepley PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-overlap_view", &flg)); 716c506a872SMatthew G. Knepley if (flg) { 717c506a872SMatthew G. Knepley PetscViewer viewer; 718c506a872SMatthew G. Knepley PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &viewer)); 719c506a872SMatthew G. Knepley PetscCall(DMLabelView(ovAdjByRank, viewer)); 720c506a872SMatthew G. Knepley } 721c506a872SMatthew G. Knepley /* Invert sender to receiver label */ 722c506a872SMatthew G. Knepley PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel)); 723c506a872SMatthew G. Knepley PetscCall(DMPlexPartitionLabelInvert(dm, ovAdjByRank, NULL, *ovLabel)); 724c506a872SMatthew G. Knepley /* Add owned points, except for shared local points */ 725c506a872SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) PetscCall(DMLabelSetValue(*ovLabel, p, rank)); 726c506a872SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 727c506a872SMatthew G. Knepley PetscCall(DMLabelClearValue(*ovLabel, local[l], rank)); 728c506a872SMatthew G. Knepley PetscCall(DMLabelSetValue(*ovLabel, remote[l].index, remote[l].rank)); 729c506a872SMatthew G. Knepley } 730c506a872SMatthew G. Knepley /* Clean up */ 731c506a872SMatthew G. Knepley PetscCall(DMLabelDestroy(&ovAdjByRank)); 7323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 733c506a872SMatthew G. Knepley } 734c506a872SMatthew G. Knepley 735cc4c1da9SBarry Smith /*@ 73620f4b53cSBarry Smith DMPlexCreateOverlapMigrationSF - Create a `PetscSF` describing the new mesh distribution to make the overlap described by the input `PetscSF` 73724cc2ca5SMatthew G. Knepley 73820f4b53cSBarry Smith Collective 73924cc2ca5SMatthew G. Knepley 74024cc2ca5SMatthew G. Knepley Input Parameters: 74120f4b53cSBarry Smith + dm - The `DM` 74220f4b53cSBarry Smith - overlapSF - The `PetscSF` mapping ghost points in overlap to owner points on other processes 74324cc2ca5SMatthew G. Knepley 744064ec1f3Sprj- Output Parameter: 74520f4b53cSBarry Smith . migrationSF - A `PetscSF` that maps original points in old locations to points in new locations 74624cc2ca5SMatthew G. Knepley 74724cc2ca5SMatthew G. Knepley Level: developer 74824cc2ca5SMatthew G. Knepley 74920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabel()`, `DMPlexDistributeOverlap()`, `DMPlexDistribute()` 75024cc2ca5SMatthew G. Knepley @*/ 751d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateOverlapMigrationSF(DM dm, PetscSF overlapSF, PetscSF *migrationSF) 752d71ae5a4SJacob Faibussowitsch { 75346f9b1c3SMichael Lange MPI_Comm comm; 7549852e123SBarry Smith PetscMPIInt rank, size; 75546f9b1c3SMichael Lange PetscInt d, dim, p, pStart, pEnd, nroots, nleaves, newLeaves, point, numSharedPoints; 75646f9b1c3SMichael Lange PetscInt *pointDepths, *remoteDepths, *ilocal; 75746f9b1c3SMichael Lange PetscInt *depthRecv, *depthShift, *depthIdx; 75846f9b1c3SMichael Lange PetscSFNode *iremote; 75946f9b1c3SMichael Lange PetscSF pointSF; 76046f9b1c3SMichael Lange const PetscInt *sharedLocal; 76146f9b1c3SMichael Lange const PetscSFNode *overlapRemote, *sharedRemote; 76246f9b1c3SMichael Lange 76346f9b1c3SMichael Lange PetscFunctionBegin; 76446f9b1c3SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7659566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 7669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 7689566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 76946f9b1c3SMichael Lange 77046f9b1c3SMichael Lange /* Before building the migration SF we need to know the new stratum offsets */ 7719566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(overlapSF, &nroots, &nleaves, NULL, &overlapRemote)); 7729566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths)); 77346f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) { 7749566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 77546f9b1c3SMichael Lange for (p = pStart; p < pEnd; p++) pointDepths[p] = d; 77646f9b1c3SMichael Lange } 77746f9b1c3SMichael Lange for (p = 0; p < nleaves; p++) remoteDepths[p] = -1; 7789566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(overlapSF, MPIU_INT, pointDepths, remoteDepths, MPI_REPLACE)); 7799566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(overlapSF, MPIU_INT, pointDepths, remoteDepths, MPI_REPLACE)); 78046f9b1c3SMichael Lange 7812d4ee042Sprj- /* Count received points in each stratum and compute the internal strata shift */ 7829566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim + 1, &depthRecv, dim + 1, &depthShift, dim + 1, &depthIdx)); 78346f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) depthRecv[d] = 0; 78446f9b1c3SMichael Lange for (p = 0; p < nleaves; p++) depthRecv[remoteDepths[p]]++; 78546f9b1c3SMichael Lange depthShift[dim] = 0; 78646f9b1c3SMichael Lange for (d = 0; d < dim; d++) depthShift[d] = depthRecv[dim]; 78746f9b1c3SMichael Lange for (d = 1; d < dim; d++) depthShift[d] += depthRecv[0]; 78846f9b1c3SMichael Lange for (d = dim - 2; d > 0; d--) depthShift[d] += depthRecv[d + 1]; 78946f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) { 7909566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 79146f9b1c3SMichael Lange depthIdx[d] = pStart + depthShift[d]; 79246f9b1c3SMichael Lange } 79346f9b1c3SMichael Lange 79446f9b1c3SMichael Lange /* Form the overlap SF build an SF that describes the full overlap migration SF */ 7959566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 79646f9b1c3SMichael Lange newLeaves = pEnd - pStart + nleaves; 7979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newLeaves, &ilocal)); 7989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newLeaves, &iremote)); 79946f9b1c3SMichael Lange /* First map local points to themselves */ 80046f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) { 8019566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 80246f9b1c3SMichael Lange for (p = pStart; p < pEnd; p++) { 80346f9b1c3SMichael Lange point = p + depthShift[d]; 80446f9b1c3SMichael Lange ilocal[point] = point; 80546f9b1c3SMichael Lange iremote[point].index = p; 80646f9b1c3SMichael Lange iremote[point].rank = rank; 80746f9b1c3SMichael Lange depthIdx[d]++; 80846f9b1c3SMichael Lange } 80946f9b1c3SMichael Lange } 81046f9b1c3SMichael Lange 81146f9b1c3SMichael Lange /* Add in the remote roots for currently shared points */ 8129566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &pointSF)); 8139566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, NULL, &numSharedPoints, &sharedLocal, &sharedRemote)); 81446f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) { 8159566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 81646f9b1c3SMichael Lange for (p = 0; p < numSharedPoints; p++) { 81746f9b1c3SMichael Lange if (pStart <= sharedLocal[p] && sharedLocal[p] < pEnd) { 81846f9b1c3SMichael Lange point = sharedLocal[p] + depthShift[d]; 81946f9b1c3SMichael Lange iremote[point].index = sharedRemote[p].index; 82046f9b1c3SMichael Lange iremote[point].rank = sharedRemote[p].rank; 82146f9b1c3SMichael Lange } 82246f9b1c3SMichael Lange } 82346f9b1c3SMichael Lange } 82446f9b1c3SMichael Lange 82546f9b1c3SMichael Lange /* Now add the incoming overlap points */ 82646f9b1c3SMichael Lange for (p = 0; p < nleaves; p++) { 82746f9b1c3SMichael Lange point = depthIdx[remoteDepths[p]]; 82846f9b1c3SMichael Lange ilocal[point] = point; 82946f9b1c3SMichael Lange iremote[point].index = overlapRemote[p].index; 83046f9b1c3SMichael Lange iremote[point].rank = overlapRemote[p].rank; 83146f9b1c3SMichael Lange depthIdx[remoteDepths[p]]++; 83246f9b1c3SMichael Lange } 8339566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointDepths, remoteDepths)); 83446f9b1c3SMichael Lange 8359566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, migrationSF)); 8369566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*migrationSF, "Overlap Migration SF")); 8379566063dSJacob Faibussowitsch PetscCall(PetscSFSetFromOptions(*migrationSF)); 8389566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8399566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*migrationSF, pEnd - pStart, newLeaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 84046f9b1c3SMichael Lange 8419566063dSJacob Faibussowitsch PetscCall(PetscFree3(depthRecv, depthShift, depthIdx)); 8423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 84370034214SMatthew G. Knepley } 84470034214SMatthew G. Knepley 845a9f1d5b2SMichael Lange /*@ 846f0e73a3dSToby Isaac DMPlexStratifyMigrationSF - Rearrange the leaves of a migration sf for stratification. 847a9f1d5b2SMichael Lange 848064ec1f3Sprj- Input Parameters: 849a9f1d5b2SMichael Lange + dm - The DM 850a9f1d5b2SMichael Lange - sf - A star forest with non-ordered leaves, usually defining a DM point migration 851a9f1d5b2SMichael Lange 852a9f1d5b2SMichael Lange Output Parameter: 853a9f1d5b2SMichael Lange . migrationSF - A star forest with added leaf indirection that ensures the resulting DM is stratified 854a9f1d5b2SMichael Lange 85520f4b53cSBarry Smith Level: developer 85620f4b53cSBarry Smith 857412e9a14SMatthew G. Knepley Note: 858412e9a14SMatthew G. Knepley This lexicographically sorts by (depth, cellType) 859412e9a14SMatthew G. Knepley 86020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 861a9f1d5b2SMichael Lange @*/ 862d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratifyMigrationSF(DM dm, PetscSF sf, PetscSF *migrationSF) 863d71ae5a4SJacob Faibussowitsch { 864a9f1d5b2SMichael Lange MPI_Comm comm; 8659852e123SBarry Smith PetscMPIInt rank, size; 866412e9a14SMatthew G. Knepley PetscInt d, ldepth, depth, dim, p, pStart, pEnd, nroots, nleaves; 867412e9a14SMatthew G. Knepley PetscSFNode *pointDepths, *remoteDepths; 868412e9a14SMatthew G. Knepley PetscInt *ilocal; 869a9f1d5b2SMichael Lange PetscInt *depthRecv, *depthShift, *depthIdx; 870412e9a14SMatthew G. Knepley PetscInt *ctRecv, *ctShift, *ctIdx; 871a9f1d5b2SMichael Lange const PetscSFNode *iremote; 872a9f1d5b2SMichael Lange 873a9f1d5b2SMichael Lange PetscFunctionBegin; 874a9f1d5b2SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8759566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 8769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 8779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 8789566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &ldepth)); 8799566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 880462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&ldepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 88163a3b9bcSJacob Faibussowitsch PetscCheck(!(ldepth >= 0) || !(depth != ldepth), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %" PetscInt_FMT " != %" PetscInt_FMT, ldepth, depth); 8829566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartStratSF, dm, 0, 0, 0)); 883a9f1d5b2SMichael Lange 884a9f1d5b2SMichael Lange /* Before building the migration SF we need to know the new stratum offsets */ 8859566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, &iremote)); 8869566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths)); 8877fab53ddSMatthew G. Knepley for (d = 0; d < depth + 1; ++d) { 8889566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 889f0e73a3dSToby Isaac for (p = pStart; p < pEnd; ++p) { 890412e9a14SMatthew G. Knepley DMPolytopeType ct; 891f0e73a3dSToby Isaac 8929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 893412e9a14SMatthew G. Knepley pointDepths[p].index = d; 894412e9a14SMatthew G. Knepley pointDepths[p].rank = ct; 895f0e73a3dSToby Isaac } 896412e9a14SMatthew G. Knepley } 8979371c9d4SSatish Balay for (p = 0; p < nleaves; ++p) { 8989371c9d4SSatish Balay remoteDepths[p].index = -1; 8999371c9d4SSatish Balay remoteDepths[p].rank = -1; 9009371c9d4SSatish Balay } 9016497c311SBarry Smith PetscCall(PetscSFBcastBegin(sf, MPIU_SF_NODE, pointDepths, remoteDepths, MPI_REPLACE)); 9026497c311SBarry Smith PetscCall(PetscSFBcastEnd(sf, MPIU_SF_NODE, pointDepths, remoteDepths, MPI_REPLACE)); 903412e9a14SMatthew G. Knepley /* Count received points in each stratum and compute the internal strata shift */ 9049566063dSJacob Faibussowitsch PetscCall(PetscCalloc6(depth + 1, &depthRecv, depth + 1, &depthShift, depth + 1, &depthIdx, DM_NUM_POLYTOPES, &ctRecv, DM_NUM_POLYTOPES, &ctShift, DM_NUM_POLYTOPES, &ctIdx)); 905412e9a14SMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 906412e9a14SMatthew G. Knepley if (remoteDepths[p].rank < 0) { 907412e9a14SMatthew G. Knepley ++depthRecv[remoteDepths[p].index]; 908412e9a14SMatthew G. Knepley } else { 909412e9a14SMatthew G. Knepley ++ctRecv[remoteDepths[p].rank]; 910412e9a14SMatthew G. Knepley } 911412e9a14SMatthew G. Knepley } 912412e9a14SMatthew G. Knepley { 913412e9a14SMatthew G. Knepley PetscInt depths[4], dims[4], shift = 0, i, c; 914412e9a14SMatthew G. Knepley 9158238f61eSMatthew G. Knepley /* Cells (depth), Vertices (0), Faces (depth-1), Edges (1) 916476787b7SMatthew G. Knepley Consider DM_POLYTOPE_FV_GHOST, DM_POLYTOPE_INTERIOR_GHOST and DM_POLYTOPE_UNKNOWN_CELL as cells 9178238f61eSMatthew G. Knepley */ 9189371c9d4SSatish Balay depths[0] = depth; 9199371c9d4SSatish Balay depths[1] = 0; 9209371c9d4SSatish Balay depths[2] = depth - 1; 9219371c9d4SSatish Balay depths[3] = 1; 9229371c9d4SSatish Balay dims[0] = dim; 9239371c9d4SSatish Balay dims[1] = 0; 9249371c9d4SSatish Balay dims[2] = dim - 1; 9259371c9d4SSatish Balay dims[3] = 1; 926412e9a14SMatthew G. Knepley for (i = 0; i <= depth; ++i) { 927412e9a14SMatthew G. Knepley const PetscInt dep = depths[i]; 928412e9a14SMatthew G. Knepley const PetscInt dim = dims[i]; 929412e9a14SMatthew G. Knepley 930412e9a14SMatthew G. Knepley for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 931476787b7SMatthew 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; 932412e9a14SMatthew G. Knepley ctShift[c] = shift; 933412e9a14SMatthew G. Knepley shift += ctRecv[c]; 934412e9a14SMatthew G. Knepley } 935412e9a14SMatthew G. Knepley depthShift[dep] = shift; 936412e9a14SMatthew G. Knepley shift += depthRecv[dep]; 937412e9a14SMatthew G. Knepley } 938412e9a14SMatthew G. Knepley for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 939412e9a14SMatthew G. Knepley const PetscInt ctDim = DMPolytopeTypeGetDim((DMPolytopeType)c); 940412e9a14SMatthew G. Knepley 941476787b7SMatthew G. Knepley if ((ctDim < 0 || ctDim > dim) && (c != DM_POLYTOPE_FV_GHOST && c != DM_POLYTOPE_INTERIOR_GHOST && c != DM_POLYTOPE_UNKNOWN_CELL)) { 942412e9a14SMatthew G. Knepley ctShift[c] = shift; 943412e9a14SMatthew G. Knepley shift += ctRecv[c]; 944412e9a14SMatthew G. Knepley } 945412e9a14SMatthew G. Knepley } 946412e9a14SMatthew G. Knepley } 947a9f1d5b2SMichael Lange /* Derive a new local permutation based on stratified indices */ 9489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &ilocal)); 9497fab53ddSMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 950412e9a14SMatthew G. Knepley const DMPolytopeType ct = (DMPolytopeType)remoteDepths[p].rank; 9517fab53ddSMatthew G. Knepley 952412e9a14SMatthew G. Knepley ilocal[p] = ctShift[ct] + ctIdx[ct]; 953412e9a14SMatthew G. Knepley ++ctIdx[ct]; 954412e9a14SMatthew G. Knepley } 9559566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, migrationSF)); 9569566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*migrationSF, "Migration SF")); 9579566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*migrationSF, nroots, nleaves, ilocal, PETSC_OWN_POINTER, (PetscSFNode *)iremote, PETSC_COPY_VALUES)); 9589566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointDepths, remoteDepths)); 9599566063dSJacob Faibussowitsch PetscCall(PetscFree6(depthRecv, depthShift, depthIdx, ctRecv, ctShift, ctIdx)); 9609566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartStratSF, dm, 0, 0, 0)); 9613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 962a9f1d5b2SMichael Lange } 963a9f1d5b2SMichael Lange 96470034214SMatthew G. Knepley /*@ 96520f4b53cSBarry Smith DMPlexDistributeField - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 96670034214SMatthew G. Knepley 96720f4b53cSBarry Smith Collective 96870034214SMatthew G. Knepley 96970034214SMatthew G. Knepley Input Parameters: 97020f4b53cSBarry Smith + dm - The `DMPLEX` object 97120f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 97220f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 973cb15cd0eSMatthew G. Knepley - originalVec - The existing data in a local vector 97470034214SMatthew G. Knepley 97570034214SMatthew G. Knepley Output Parameters: 97620f4b53cSBarry Smith + newSection - The `PetscSF` describing the new data layout 977cb15cd0eSMatthew G. Knepley - newVec - The new data in a local vector 97870034214SMatthew G. Knepley 97970034214SMatthew G. Knepley Level: developer 98070034214SMatthew G. Knepley 98120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeFieldIS()`, `DMPlexDistributeData()` 98270034214SMatthew G. Knepley @*/ 983d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 984d71ae5a4SJacob Faibussowitsch { 98570034214SMatthew G. Knepley PetscSF fieldSF; 98670034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize; 98770034214SMatthew G. Knepley PetscScalar *originalValues, *newValues; 98870034214SMatthew G. Knepley 98970034214SMatthew G. Knepley PetscFunctionBegin; 9909566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeField, dm, 0, 0, 0)); 9919566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 99270034214SMatthew G. Knepley 9939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 9949566063dSJacob Faibussowitsch PetscCall(VecSetSizes(newVec, fieldSize, PETSC_DETERMINE)); 9959566063dSJacob Faibussowitsch PetscCall(VecSetType(newVec, dm->vectype)); 99670034214SMatthew G. Knepley 9979566063dSJacob Faibussowitsch PetscCall(VecGetArray(originalVec, &originalValues)); 9989566063dSJacob Faibussowitsch PetscCall(VecGetArray(newVec, &newValues)); 9999566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 10009566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 10019566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues, MPI_REPLACE)); 10029566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues, MPI_REPLACE)); 10039566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 10049566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(newVec, &newValues)); 10059566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(originalVec, &originalValues)); 10069566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeField, dm, 0, 0, 0)); 10073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100870034214SMatthew G. Knepley } 100970034214SMatthew G. Knepley 101070034214SMatthew G. Knepley /*@ 101120f4b53cSBarry Smith DMPlexDistributeFieldIS - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 101270034214SMatthew G. Knepley 101320f4b53cSBarry Smith Collective 101470034214SMatthew G. Knepley 101570034214SMatthew G. Knepley Input Parameters: 101620f4b53cSBarry Smith + dm - The `DMPLEX` object 101720f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 101820f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 101970034214SMatthew G. Knepley - originalIS - The existing data 102070034214SMatthew G. Knepley 102170034214SMatthew G. Knepley Output Parameters: 102220f4b53cSBarry Smith + newSection - The `PetscSF` describing the new data layout 102370034214SMatthew G. Knepley - newIS - The new data 102470034214SMatthew G. Knepley 102570034214SMatthew G. Knepley Level: developer 102670034214SMatthew G. Knepley 102720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexDistributeData()` 102870034214SMatthew G. Knepley @*/ 1029d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeFieldIS(DM dm, PetscSF pointSF, PetscSection originalSection, IS originalIS, PetscSection newSection, IS *newIS) 1030d71ae5a4SJacob Faibussowitsch { 103170034214SMatthew G. Knepley PetscSF fieldSF; 103270034214SMatthew G. Knepley PetscInt *newValues, *remoteOffsets, fieldSize; 103370034214SMatthew G. Knepley const PetscInt *originalValues; 103470034214SMatthew G. Knepley 103570034214SMatthew G. Knepley PetscFunctionBegin; 10369566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeField, dm, 0, 0, 0)); 10379566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 103870034214SMatthew G. Knepley 10399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 10409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(fieldSize, &newValues)); 104170034214SMatthew G. Knepley 10429566063dSJacob Faibussowitsch PetscCall(ISGetIndices(originalIS, &originalValues)); 10439566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 10449566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 10459566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, MPIU_INT, (PetscInt *)originalValues, newValues, MPI_REPLACE)); 10469566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, MPIU_INT, (PetscInt *)originalValues, newValues, MPI_REPLACE)); 10479566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 10489566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(originalIS, &originalValues)); 10499566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pointSF), fieldSize, newValues, PETSC_OWN_POINTER, newIS)); 10509566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeField, dm, 0, 0, 0)); 10513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 105270034214SMatthew G. Knepley } 105370034214SMatthew G. Knepley 105470034214SMatthew G. Knepley /*@ 105520f4b53cSBarry Smith DMPlexDistributeData - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 105670034214SMatthew G. Knepley 105720f4b53cSBarry Smith Collective 105870034214SMatthew G. Knepley 105970034214SMatthew G. Knepley Input Parameters: 106020f4b53cSBarry Smith + dm - The `DMPLEX` object 106120f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 106220f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 106370034214SMatthew G. Knepley . datatype - The type of data 106470034214SMatthew G. Knepley - originalData - The existing data 106570034214SMatthew G. Knepley 106670034214SMatthew G. Knepley Output Parameters: 106720f4b53cSBarry Smith + newSection - The `PetscSection` describing the new data layout 106870034214SMatthew G. Knepley - newData - The new data 106970034214SMatthew G. Knepley 107070034214SMatthew G. Knepley Level: developer 107170034214SMatthew G. Knepley 107220f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeField()` 107370034214SMatthew G. Knepley @*/ 1074d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeData(DM dm, PetscSF pointSF, PetscSection originalSection, MPI_Datatype datatype, void *originalData, PetscSection newSection, void **newData) 1075d71ae5a4SJacob Faibussowitsch { 107670034214SMatthew G. Knepley PetscSF fieldSF; 107770034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize; 107870034214SMatthew G. Knepley PetscMPIInt dataSize; 107970034214SMatthew G. Knepley 108070034214SMatthew G. Knepley PetscFunctionBegin; 10819566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeData, dm, 0, 0, 0)); 10829566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 108370034214SMatthew G. Knepley 10849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 10859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_size(datatype, &dataSize)); 10869566063dSJacob Faibussowitsch PetscCall(PetscMalloc(fieldSize * dataSize, newData)); 108770034214SMatthew G. Knepley 10889566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 10899566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 10909566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, datatype, originalData, *newData, MPI_REPLACE)); 10919566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, datatype, originalData, *newData, MPI_REPLACE)); 10929566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 10939566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeData, dm, 0, 0, 0)); 10943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 109570034214SMatthew G. Knepley } 109670034214SMatthew G. Knepley 1097d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeCones(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel) 1098d71ae5a4SJacob Faibussowitsch { 109957508eceSPierre Jolivet DM_Plex *pmesh = (DM_Plex *)dmParallel->data; 1100cc71bff1SMichael Lange MPI_Comm comm; 1101cc71bff1SMichael Lange PetscSF coneSF; 1102cc71bff1SMichael Lange PetscSection originalConeSection, newConeSection; 1103ac04eaf7SToby Isaac PetscInt *remoteOffsets, *cones, *globCones, *newCones, newConesSize; 1104cc71bff1SMichael Lange PetscBool flg; 1105cc71bff1SMichael Lange 1106cc71bff1SMichael Lange PetscFunctionBegin; 1107cc71bff1SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 11080c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5); 11099566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeCones, dm, 0, 0, 0)); 1110cc71bff1SMichael Lange /* Distribute cone section */ 11119566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 11129566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &originalConeSection)); 11139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dmParallel, &newConeSection)); 11149566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(migrationSF, originalConeSection, &remoteOffsets, newConeSection)); 11159566063dSJacob Faibussowitsch PetscCall(DMSetUp(dmParallel)); 1116cc71bff1SMichael Lange /* Communicate and renumber cones */ 11179566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(migrationSF, originalConeSection, remoteOffsets, newConeSection, &coneSF)); 11189566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 11199566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 1120ac04eaf7SToby Isaac if (original) { 1121ac04eaf7SToby Isaac PetscInt numCones; 1122ac04eaf7SToby Isaac 11239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(originalConeSection, &numCones)); 11249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCones, &globCones)); 11259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(original, numCones, cones, globCones)); 1126367003a6SStefano Zampini } else { 1127ac04eaf7SToby Isaac globCones = cones; 1128ac04eaf7SToby Isaac } 11299566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dmParallel, &newCones)); 11309566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coneSF, MPIU_INT, globCones, newCones, MPI_REPLACE)); 11319566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coneSF, MPIU_INT, globCones, newCones, MPI_REPLACE)); 11321baa6e33SBarry Smith if (original) PetscCall(PetscFree(globCones)); 11339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newConeSection, &newConesSize)); 11349566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones)); 113576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 11363533c52bSMatthew G. Knepley PetscInt p; 11373533c52bSMatthew G. Knepley PetscBool valid = PETSC_TRUE; 11383533c52bSMatthew G. Knepley for (p = 0; p < newConesSize; ++p) { 11399371c9d4SSatish Balay if (newCones[p] < 0) { 11409371c9d4SSatish Balay valid = PETSC_FALSE; 11419371c9d4SSatish Balay PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Point %" PetscInt_FMT " not in overlap SF\n", PetscGlobalRank, p)); 11429371c9d4SSatish Balay } 11433533c52bSMatthew G. Knepley } 114428b400f6SJacob Faibussowitsch PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map"); 11453533c52bSMatthew G. Knepley } 11469566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-cones_view", &flg)); 1147cc71bff1SMichael Lange if (flg) { 11489566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Serial Cone Section:\n")); 11499566063dSJacob Faibussowitsch PetscCall(PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_(comm))); 11509566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Parallel Cone Section:\n")); 11519566063dSJacob Faibussowitsch PetscCall(PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_(comm))); 11529566063dSJacob Faibussowitsch PetscCall(PetscSFView(coneSF, NULL)); 1153cc71bff1SMichael Lange } 11549566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dm, &cones)); 11559566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dmParallel, &newCones)); 11569566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones, MPI_REPLACE)); 11579566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones, MPI_REPLACE)); 11589566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coneSF)); 11599566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeCones, dm, 0, 0, 0)); 1160eaf898f9SPatrick Sanan /* Create supports and stratify DMPlex */ 1161cc71bff1SMichael Lange { 1162cc71bff1SMichael Lange PetscInt pStart, pEnd; 1163cc71bff1SMichael Lange 11649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd)); 11659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(pmesh->supportSection, pStart, pEnd)); 1166cc71bff1SMichael Lange } 11679566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dmParallel)); 11689566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dmParallel)); 11691cf84007SMatthew G. Knepley { 11701cf84007SMatthew G. Knepley PetscBool useCone, useClosure, useAnchors; 11711cf84007SMatthew G. Knepley 11729566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 11739566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dmParallel, useCone, useClosure)); 11749566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors)); 11759566063dSJacob Faibussowitsch PetscCall(DMPlexSetAdjacencyUseAnchors(dmParallel, useAnchors)); 11761cf84007SMatthew G. Knepley } 11773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1178cc71bff1SMichael Lange } 1179cc71bff1SMichael Lange 1180d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeCoordinates(DM dm, PetscSF migrationSF, DM dmParallel) 1181d71ae5a4SJacob Faibussowitsch { 11820df0e737SMichael Lange MPI_Comm comm; 11839318fe57SMatthew G. Knepley DM cdm, cdmParallel; 11840df0e737SMichael Lange PetscSection originalCoordSection, newCoordSection; 11850df0e737SMichael Lange Vec originalCoordinates, newCoordinates; 11860df0e737SMichael Lange PetscInt bs; 11870df0e737SMichael Lange const char *name; 11884fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 11890df0e737SMichael Lange 11900df0e737SMichael Lange PetscFunctionBegin; 11910df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 11920c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3); 11930df0e737SMichael Lange 11949566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 11956858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 11966858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dmParallel, &cdmParallel)); 11976858538eSMatthew G. Knepley PetscCall(DMCopyDisc(cdm, cdmParallel)); 11989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &originalCoordSection)); 11999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmParallel, &newCoordSection)); 12009566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &originalCoordinates)); 12010df0e737SMichael Lange if (originalCoordinates) { 12029566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates)); 12039566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalCoordinates, &name)); 12049566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)newCoordinates, name)); 12050df0e737SMichael Lange 12069566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates)); 12079566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmParallel, newCoordinates)); 12089566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(originalCoordinates, &bs)); 12099566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(newCoordinates, bs)); 12109566063dSJacob Faibussowitsch PetscCall(VecDestroy(&newCoordinates)); 12110df0e737SMichael Lange } 12126858538eSMatthew G. Knepley 12136858538eSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12144fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L)); 12154fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmParallel, maxCell, Lstart, L)); 12166858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdm)); 12176858538eSMatthew G. Knepley if (cdm) { 12186858538eSMatthew G. Knepley PetscCall(DMClone(dmParallel, &cdmParallel)); 12196858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmParallel, cdmParallel)); 12209566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(cdm, cdmParallel)); 12216858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmParallel)); 12226858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &originalCoordSection)); 12236858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &originalCoordinates)); 12246858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(comm, &newCoordSection)); 12256858538eSMatthew G. Knepley if (originalCoordinates) { 12266858538eSMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates)); 12276858538eSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)originalCoordinates, &name)); 12286858538eSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)newCoordinates, name)); 12296858538eSMatthew G. Knepley 12306858538eSMatthew G. Knepley PetscCall(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates)); 12316858538eSMatthew G. Knepley PetscCall(VecGetBlockSize(originalCoordinates, &bs)); 12326858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(newCoordinates, bs)); 12336858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(dmParallel, bs, newCoordSection)); 12346858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmParallel, newCoordinates)); 12356858538eSMatthew G. Knepley PetscCall(VecDestroy(&newCoordinates)); 12366858538eSMatthew G. Knepley } 12376858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&newCoordSection)); 12386858538eSMatthew G. Knepley } 12393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12400df0e737SMichael Lange } 12410df0e737SMichael Lange 1242d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeLabels(DM dm, PetscSF migrationSF, DM dmParallel) 1243d71ae5a4SJacob Faibussowitsch { 1244df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 12450df0e737SMichael Lange MPI_Comm comm; 12467980c9d4SMatthew G. Knepley DMLabel depthLabel; 12470df0e737SMichael Lange PetscMPIInt rank; 12487980c9d4SMatthew G. Knepley PetscInt depth, d, numLabels, numLocalLabels, l; 1249df0420ecSMatthew G. Knepley PetscBool hasLabels = PETSC_FALSE, lsendDepth, sendDepth; 1250df0420ecSMatthew G. Knepley PetscObjectState depthState = -1; 12510df0e737SMichael Lange 12520df0e737SMichael Lange PetscFunctionBegin; 12530df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 12540c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3); 12550c86c063SLisandro Dalcin 12569566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeLabels, dm, 0, 0, 0)); 12579566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 12590df0e737SMichael Lange 1260df0420ecSMatthew G. Knepley /* If the user has changed the depth label, communicate it instead */ 12619566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 12629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 12639566063dSJacob Faibussowitsch if (depthLabel) PetscCall(PetscObjectStateGet((PetscObject)depthLabel, &depthState)); 1264df0420ecSMatthew G. Knepley lsendDepth = mesh->depthState != depthState ? PETSC_TRUE : PETSC_FALSE; 1265462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&lsendDepth, &sendDepth, 1, MPIU_BOOL, MPI_LOR, comm)); 1266df0420ecSMatthew G. Knepley if (sendDepth) { 12679566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dmParallel, &dmParallel->depthLabel)); 12689566063dSJacob Faibussowitsch PetscCall(DMRemoveLabelBySelf(dmParallel, &dmParallel->depthLabel, PETSC_FALSE)); 1269df0420ecSMatthew G. Knepley } 1270d995df53SMatthew G. Knepley /* Everyone must have either the same number of labels, or none */ 12719566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLocalLabels)); 1272d995df53SMatthew G. Knepley numLabels = numLocalLabels; 12739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm)); 1274627847f0SMatthew G. Knepley if (numLabels == numLocalLabels) hasLabels = PETSC_TRUE; 12755d80c0bfSVaclav Hapla for (l = 0; l < numLabels; ++l) { 1276bdd2d751SMichael Lange DMLabel label = NULL, labelNew = NULL; 127783e10cb3SLisandro Dalcin PetscBool isDepth, lisOutput = PETSC_TRUE, isOutput; 1278d67d17b1SMatthew G. Knepley const char *name = NULL; 12790df0e737SMichael Lange 1280d67d17b1SMatthew G. Knepley if (hasLabels) { 12819566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(dm, l, &label)); 12820df0e737SMichael Lange /* Skip "depth" because it is recreated */ 12839566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)label, &name)); 12849566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 1285bbcf679cSJacob Faibussowitsch } else { 1286bbcf679cSJacob Faibussowitsch isDepth = PETSC_FALSE; 1287d67d17b1SMatthew G. Knepley } 12889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&isDepth, 1, MPIU_BOOL, 0, comm)); 128983e10cb3SLisandro Dalcin if (isDepth && !sendDepth) continue; 12909566063dSJacob Faibussowitsch PetscCall(DMLabelDistribute(label, migrationSF, &labelNew)); 129183e10cb3SLisandro Dalcin if (isDepth) { 12927980c9d4SMatthew G. Knepley /* Put in any missing strata which can occur if users are managing the depth label themselves */ 12937980c9d4SMatthew G. Knepley PetscInt gdepth; 12947980c9d4SMatthew G. Knepley 1295462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&depth, &gdepth, 1, MPIU_INT, MPI_MAX, comm)); 129663a3b9bcSJacob Faibussowitsch PetscCheck(!(depth >= 0) || !(gdepth != depth), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %" PetscInt_FMT " != %" PetscInt_FMT, depth, gdepth); 12977980c9d4SMatthew G. Knepley for (d = 0; d <= gdepth; ++d) { 12987980c9d4SMatthew G. Knepley PetscBool has; 12997980c9d4SMatthew G. Knepley 13009566063dSJacob Faibussowitsch PetscCall(DMLabelHasStratum(labelNew, d, &has)); 13019566063dSJacob Faibussowitsch if (!has) PetscCall(DMLabelAddStratum(labelNew, d)); 13027980c9d4SMatthew G. Knepley } 13037980c9d4SMatthew G. Knepley } 13049566063dSJacob Faibussowitsch PetscCall(DMAddLabel(dmParallel, labelNew)); 130583e10cb3SLisandro Dalcin /* Put the output flag in the new label */ 13069566063dSJacob Faibussowitsch if (hasLabels) PetscCall(DMGetLabelOutput(dm, name, &lisOutput)); 1307462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&lisOutput, &isOutput, 1, MPIU_BOOL, MPI_LAND, comm)); 13089566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)labelNew, &name)); 13099566063dSJacob Faibussowitsch PetscCall(DMSetLabelOutput(dmParallel, name, isOutput)); 13109566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&labelNew)); 13110df0e737SMichael Lange } 1312695799ffSMatthew G. Knepley { 1313695799ffSMatthew G. Knepley DMLabel ctLabel; 1314695799ffSMatthew G. Knepley 1315695799ffSMatthew G. Knepley // Reset label for fast lookup 1316695799ffSMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dmParallel, &ctLabel)); 1317695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 1318695799ffSMatthew G. Knepley } 13199566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeLabels, dm, 0, 0, 0)); 13203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13210df0e737SMichael Lange } 13220df0e737SMichael Lange 1323d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeSetupTree(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel) 1324d71ae5a4SJacob Faibussowitsch { 132515078cd4SMichael Lange DM_Plex *mesh = (DM_Plex *)dm->data; 132657508eceSPierre Jolivet DM_Plex *pmesh = (DM_Plex *)dmParallel->data; 1327a6f36705SMichael Lange MPI_Comm comm; 1328a6f36705SMichael Lange DM refTree; 1329a6f36705SMichael Lange PetscSection origParentSection, newParentSection; 1330a6f36705SMichael Lange PetscInt *origParents, *origChildIDs; 1331a6f36705SMichael Lange PetscBool flg; 1332a6f36705SMichael Lange 1333a6f36705SMichael Lange PetscFunctionBegin; 1334a6f36705SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13350c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5); 13369566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 1337a6f36705SMichael Lange 1338a6f36705SMichael Lange /* Set up tree */ 13399566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 13409566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(dmParallel, refTree)); 13419566063dSJacob Faibussowitsch PetscCall(DMPlexGetTree(dm, &origParentSection, &origParents, &origChildIDs, NULL, NULL)); 1342a6f36705SMichael Lange if (origParentSection) { 1343a6f36705SMichael Lange PetscInt pStart, pEnd; 134408633170SToby Isaac PetscInt *newParents, *newChildIDs, *globParents; 1345a6f36705SMichael Lange PetscInt *remoteOffsetsParents, newParentSize; 1346a6f36705SMichael Lange PetscSF parentSF; 1347a6f36705SMichael Lange 13489566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmParallel, &pStart, &pEnd)); 13499566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmParallel), &newParentSection)); 13509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newParentSection, pStart, pEnd)); 13519566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(migrationSF, origParentSection, &remoteOffsetsParents, newParentSection)); 13529566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(migrationSF, origParentSection, remoteOffsetsParents, newParentSection, &parentSF)); 13539566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsParents)); 13549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newParentSection, &newParentSize)); 13559566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(newParentSize, &newParents, newParentSize, &newChildIDs)); 135608633170SToby Isaac if (original) { 135708633170SToby Isaac PetscInt numParents; 135808633170SToby Isaac 13599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(origParentSection, &numParents)); 13609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numParents, &globParents)); 13619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(original, numParents, origParents, globParents)); 13629371c9d4SSatish Balay } else { 136308633170SToby Isaac globParents = origParents; 136408633170SToby Isaac } 13659566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(parentSF, MPIU_INT, globParents, newParents, MPI_REPLACE)); 13669566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(parentSF, MPIU_INT, globParents, newParents, MPI_REPLACE)); 13671baa6e33SBarry Smith if (original) PetscCall(PetscFree(globParents)); 13689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(parentSF, MPIU_INT, origChildIDs, newChildIDs, MPI_REPLACE)); 13699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(parentSF, MPIU_INT, origChildIDs, newChildIDs, MPI_REPLACE)); 13709566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newParentSize, newParents, NULL, newParents)); 137176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 13724a54e071SToby Isaac PetscInt p; 13734a54e071SToby Isaac PetscBool valid = PETSC_TRUE; 13744a54e071SToby Isaac for (p = 0; p < newParentSize; ++p) { 13759371c9d4SSatish Balay if (newParents[p] < 0) { 13769371c9d4SSatish Balay valid = PETSC_FALSE; 13779371c9d4SSatish Balay PetscCall(PetscPrintf(PETSC_COMM_SELF, "Point %" PetscInt_FMT " not in overlap SF\n", p)); 13789371c9d4SSatish Balay } 13794a54e071SToby Isaac } 138028b400f6SJacob Faibussowitsch PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map"); 13814a54e071SToby Isaac } 13829566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-parents_view", &flg)); 1383a6f36705SMichael Lange if (flg) { 13849566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Serial Parent Section: \n")); 13859566063dSJacob Faibussowitsch PetscCall(PetscSectionView(origParentSection, PETSC_VIEWER_STDOUT_(comm))); 13869566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Parallel Parent Section: \n")); 13879566063dSJacob Faibussowitsch PetscCall(PetscSectionView(newParentSection, PETSC_VIEWER_STDOUT_(comm))); 13889566063dSJacob Faibussowitsch PetscCall(PetscSFView(parentSF, NULL)); 1389a6f36705SMichael Lange } 13909566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(dmParallel, newParentSection, newParents, newChildIDs)); 13919566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newParentSection)); 13929566063dSJacob Faibussowitsch PetscCall(PetscFree2(newParents, newChildIDs)); 13939566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&parentSF)); 1394a6f36705SMichael Lange } 139515078cd4SMichael Lange pmesh->useAnchors = mesh->useAnchors; 13963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1397a6f36705SMichael Lange } 13980df0e737SMichael Lange 139998ba2d7fSLawrence Mitchell /*@ 140020f4b53cSBarry Smith DMPlexSetPartitionBalance - Should distribution of the `DM` attempt to balance the shared point partition? 140198ba2d7fSLawrence Mitchell 140298ba2d7fSLawrence Mitchell Input Parameters: 140320f4b53cSBarry Smith + dm - The `DMPLEX` object 140498ba2d7fSLawrence Mitchell - flg - Balance the partition? 140598ba2d7fSLawrence Mitchell 140698ba2d7fSLawrence Mitchell Level: intermediate 140798ba2d7fSLawrence Mitchell 140820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetPartitionBalance()` 140998ba2d7fSLawrence Mitchell @*/ 1410d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetPartitionBalance(DM dm, PetscBool flg) 1411d71ae5a4SJacob Faibussowitsch { 141298ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 141398ba2d7fSLawrence Mitchell 141498ba2d7fSLawrence Mitchell PetscFunctionBegin; 141598ba2d7fSLawrence Mitchell mesh->partitionBalance = flg; 14163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 141798ba2d7fSLawrence Mitchell } 141898ba2d7fSLawrence Mitchell 141998ba2d7fSLawrence Mitchell /*@ 142020f4b53cSBarry Smith DMPlexGetPartitionBalance - Does distribution of the `DM` attempt to balance the shared point partition? 142198ba2d7fSLawrence Mitchell 142298ba2d7fSLawrence Mitchell Input Parameter: 142320f4b53cSBarry Smith . dm - The `DMPLEX` object 142498ba2d7fSLawrence Mitchell 142598ba2d7fSLawrence Mitchell Output Parameter: 1426a2b725a8SWilliam Gropp . flg - Balance the partition? 142798ba2d7fSLawrence Mitchell 142898ba2d7fSLawrence Mitchell Level: intermediate 142998ba2d7fSLawrence Mitchell 143020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexSetPartitionBalance()` 143198ba2d7fSLawrence Mitchell @*/ 1432d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPartitionBalance(DM dm, PetscBool *flg) 1433d71ae5a4SJacob Faibussowitsch { 143498ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 143598ba2d7fSLawrence Mitchell 143698ba2d7fSLawrence Mitchell PetscFunctionBegin; 143798ba2d7fSLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14384f572ea9SToby Isaac PetscAssertPointer(flg, 2); 143998ba2d7fSLawrence Mitchell *flg = mesh->partitionBalance; 14403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 144198ba2d7fSLawrence Mitchell } 144298ba2d7fSLawrence Mitchell 1443fc02256fSLawrence Mitchell typedef struct { 1444fc02256fSLawrence Mitchell PetscInt vote, rank, index; 1445fc02256fSLawrence Mitchell } Petsc3Int; 1446fc02256fSLawrence Mitchell 1447fc02256fSLawrence Mitchell /* MaxLoc, but carry a third piece of information around */ 1448d71ae5a4SJacob Faibussowitsch static void MPIAPI MaxLocCarry(void *in_, void *inout_, PetscMPIInt *len_, MPI_Datatype *dtype) 1449d71ae5a4SJacob Faibussowitsch { 1450fc02256fSLawrence Mitchell Petsc3Int *a = (Petsc3Int *)inout_; 1451fc02256fSLawrence Mitchell Petsc3Int *b = (Petsc3Int *)in_; 1452fc02256fSLawrence Mitchell PetscInt i, len = *len_; 1453fc02256fSLawrence Mitchell for (i = 0; i < len; i++) { 1454fc02256fSLawrence Mitchell if (a[i].vote < b[i].vote) { 1455fc02256fSLawrence Mitchell a[i].vote = b[i].vote; 1456fc02256fSLawrence Mitchell a[i].rank = b[i].rank; 1457fc02256fSLawrence Mitchell a[i].index = b[i].index; 1458fc02256fSLawrence Mitchell } else if (a[i].vote <= b[i].vote) { 1459fc02256fSLawrence Mitchell if (a[i].rank >= b[i].rank) { 1460fc02256fSLawrence Mitchell a[i].rank = b[i].rank; 1461fc02256fSLawrence Mitchell a[i].index = b[i].index; 1462fc02256fSLawrence Mitchell } 1463fc02256fSLawrence Mitchell } 1464fc02256fSLawrence Mitchell } 1465fc02256fSLawrence Mitchell } 1466fc02256fSLawrence Mitchell 1467cc4c1da9SBarry Smith /*@ 146820f4b53cSBarry Smith DMPlexCreatePointSF - Build a point `PetscSF` from an `PetscSF` describing a point migration 1469f5bf2dbfSMichael Lange 1470064ec1f3Sprj- Input Parameters: 147120f4b53cSBarry Smith + dm - The source `DMPLEX` object 1472f5bf2dbfSMichael Lange . migrationSF - The star forest that describes the parallel point remapping 1473d8d19677SJose E. Roman - ownership - Flag causing a vote to determine point ownership 1474f5bf2dbfSMichael Lange 1475f5bf2dbfSMichael Lange Output Parameter: 147620f4b53cSBarry Smith . pointSF - The star forest describing the point overlap in the remapped `DM` 14773618482eSVaclav Hapla 1478f5bf2dbfSMichael Lange Level: developer 1479f5bf2dbfSMichael Lange 148020f4b53cSBarry Smith Note: 148120f4b53cSBarry Smith Output `pointSF` is guaranteed to have the array of local indices (leaves) sorted. 148220f4b53cSBarry Smith 148320f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 1484f5bf2dbfSMichael Lange @*/ 1485d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointSF(DM dm, PetscSF migrationSF, PetscBool ownership, PetscSF *pointSF) 1486d71ae5a4SJacob Faibussowitsch { 148723193802SMatthew G. Knepley PetscMPIInt rank, size; 14881627f6ccSMichael Lange PetscInt p, nroots, nleaves, idx, npointLeaves; 1489f5bf2dbfSMichael Lange PetscInt *pointLocal; 1490f5bf2dbfSMichael Lange const PetscInt *leaves; 1491f5bf2dbfSMichael Lange const PetscSFNode *roots; 1492f5bf2dbfSMichael Lange PetscSFNode *rootNodes, *leafNodes, *pointRemote; 149323193802SMatthew G. Knepley Vec shifts; 1494cae3e4f3SLawrence Mitchell const PetscInt numShifts = 13759; 149523193802SMatthew G. Knepley const PetscScalar *shift = NULL; 149623193802SMatthew G. Knepley const PetscBool shiftDebug = PETSC_FALSE; 149798ba2d7fSLawrence Mitchell PetscBool balance; 1498f5bf2dbfSMichael Lange 1499f5bf2dbfSMichael Lange PetscFunctionBegin; 1500f5bf2dbfSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 15019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 15039566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreatePointSF, dm, 0, 0, 0)); 1504907a3e9cSStefano Zampini PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), pointSF)); 1505907a3e9cSStefano Zampini PetscCall(PetscSFSetFromOptions(*pointSF)); 1506907a3e9cSStefano Zampini if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 1507f5bf2dbfSMichael Lange 15089566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitionBalance(dm, &balance)); 15099566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(migrationSF, &nroots, &nleaves, &leaves, &roots)); 15109566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &rootNodes, nleaves, &leafNodes)); 1511f5bf2dbfSMichael Lange if (ownership) { 1512fc02256fSLawrence Mitchell MPI_Op op; 1513fc02256fSLawrence Mitchell MPI_Datatype datatype; 1514fc02256fSLawrence Mitchell Petsc3Int *rootVote = NULL, *leafVote = NULL; 15156497c311SBarry Smith 151623193802SMatthew 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. */ 151798ba2d7fSLawrence Mitchell if (balance) { 151823193802SMatthew G. Knepley PetscRandom r; 151923193802SMatthew G. Knepley 15209566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_SELF, &r)); 15219566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(r, 0, 2467 * size)); 15229566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &shifts)); 15239566063dSJacob Faibussowitsch PetscCall(VecSetSizes(shifts, numShifts, numShifts)); 15249566063dSJacob Faibussowitsch PetscCall(VecSetType(shifts, VECSTANDARD)); 15259566063dSJacob Faibussowitsch PetscCall(VecSetRandom(shifts, r)); 15269566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&r)); 15279566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(shifts, &shift)); 152823193802SMatthew G. Knepley } 152923193802SMatthew G. Knepley 15309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nroots, &rootVote)); 15319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &leafVote)); 153223193802SMatthew G. Knepley /* Point ownership vote: Process with highest rank owns shared points */ 1533f5bf2dbfSMichael Lange for (p = 0; p < nleaves; ++p) { 153423193802SMatthew G. Knepley if (shiftDebug) { 15359371c9d4SSatish 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, 15369371c9d4SSatish Balay (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]), (rank + (shift ? (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]) : 0)) % size)); 153723193802SMatthew G. Knepley } 1538f5bf2dbfSMichael Lange /* Either put in a bid or we know we own it */ 1539fc02256fSLawrence Mitchell leafVote[p].vote = (rank + (shift ? (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]) : 0)) % size; 1540fc02256fSLawrence Mitchell leafVote[p].rank = rank; 1541fc02256fSLawrence Mitchell leafVote[p].index = p; 1542f5bf2dbfSMichael Lange } 1543f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) { 15441627f6ccSMichael Lange /* Root must not participate in the reduction, flag so that MAXLOC does not use */ 1545fc02256fSLawrence Mitchell rootVote[p].vote = -3; 1546fc02256fSLawrence Mitchell rootVote[p].rank = -3; 1547fc02256fSLawrence Mitchell rootVote[p].index = -3; 1548f5bf2dbfSMichael Lange } 15499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(3, MPIU_INT, &datatype)); 15509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&datatype)); 15519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(&MaxLocCarry, 1, &op)); 15529566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(migrationSF, datatype, leafVote, rootVote, op)); 15539566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(migrationSF, datatype, leafVote, rootVote, op)); 15549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&op)); 15559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&datatype)); 1556c091126eSLawrence Mitchell for (p = 0; p < nroots; p++) { 1557835f2295SStefano Zampini rootNodes[p].rank = rootVote[p].rank; 1558fc02256fSLawrence Mitchell rootNodes[p].index = rootVote[p].index; 1559c091126eSLawrence Mitchell } 15609566063dSJacob Faibussowitsch PetscCall(PetscFree(leafVote)); 15619566063dSJacob Faibussowitsch PetscCall(PetscFree(rootVote)); 1562f5bf2dbfSMichael Lange } else { 1563f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) { 1564f5bf2dbfSMichael Lange rootNodes[p].index = -1; 1565f5bf2dbfSMichael Lange rootNodes[p].rank = rank; 1566fc02256fSLawrence Mitchell } 1567f5bf2dbfSMichael Lange for (p = 0; p < nleaves; p++) { 1568f5bf2dbfSMichael Lange /* Write new local id into old location */ 1569ad540459SPierre Jolivet if (roots[p].rank == rank) rootNodes[roots[p].index].index = leaves ? leaves[p] : p; 1570f5bf2dbfSMichael Lange } 1571f5bf2dbfSMichael Lange } 15726497c311SBarry Smith PetscCall(PetscSFBcastBegin(migrationSF, MPIU_SF_NODE, rootNodes, leafNodes, MPI_REPLACE)); 15736497c311SBarry Smith PetscCall(PetscSFBcastEnd(migrationSF, MPIU_SF_NODE, rootNodes, leafNodes, MPI_REPLACE)); 1574f5bf2dbfSMichael Lange 157523193802SMatthew G. Knepley for (npointLeaves = 0, p = 0; p < nleaves; p++) { 1576b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) npointLeaves++; 157723193802SMatthew G. Knepley } 15789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npointLeaves, &pointLocal)); 15799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npointLeaves, &pointRemote)); 1580f5bf2dbfSMichael Lange for (idx = 0, p = 0; p < nleaves; p++) { 1581b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) { 15823618482eSVaclav Hapla /* Note that pointLocal is automatically sorted as it is sublist of 0, ..., nleaves-1 */ 1583f5bf2dbfSMichael Lange pointLocal[idx] = p; 1584f5bf2dbfSMichael Lange pointRemote[idx] = leafNodes[p]; 1585f5bf2dbfSMichael Lange idx++; 1586f5bf2dbfSMichael Lange } 1587f5bf2dbfSMichael Lange } 158823193802SMatthew G. Knepley if (shift) { 15899566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(shifts, &shift)); 15909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shifts)); 159123193802SMatthew G. Knepley } 15929566063dSJacob Faibussowitsch if (shiftDebug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), PETSC_STDOUT)); 15939566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*pointSF, nleaves, npointLeaves, pointLocal, PETSC_OWN_POINTER, pointRemote, PETSC_OWN_POINTER)); 15949566063dSJacob Faibussowitsch PetscCall(PetscFree2(rootNodes, leafNodes)); 15959566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreatePointSF, dm, 0, 0, 0)); 1596d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, *pointSF, PETSC_FALSE)); 15973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1598f5bf2dbfSMichael Lange } 1599f5bf2dbfSMichael Lange 1600cc4c1da9SBarry Smith /*@ 160120f4b53cSBarry Smith DMPlexMigrate - Migrates internal `DM` data over the supplied star forest 160215078cd4SMichael Lange 160320f4b53cSBarry Smith Collective 160483655b49SVáclav Hapla 1605064ec1f3Sprj- Input Parameters: 160620f4b53cSBarry Smith + dm - The source `DMPLEX` object 1607d8d19677SJose E. Roman - sf - The star forest communication context describing the migration pattern 160815078cd4SMichael Lange 160915078cd4SMichael Lange Output Parameter: 161020f4b53cSBarry Smith . targetDM - The target `DMPLEX` object 161115078cd4SMichael Lange 1612b9f40539SMichael Lange Level: intermediate 161315078cd4SMichael Lange 161420f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 161515078cd4SMichael Lange @*/ 1616d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMigrate(DM dm, PetscSF sf, DM targetDM) 1617d71ae5a4SJacob Faibussowitsch { 1618b9f40539SMichael Lange MPI_Comm comm; 1619cc1750acSStefano Zampini PetscInt dim, cdim, nroots; 1620b9f40539SMichael Lange PetscSF sfPoint; 162115078cd4SMichael Lange ISLocalToGlobalMapping ltogMigration; 1622ac04eaf7SToby Isaac ISLocalToGlobalMapping ltogOriginal = NULL; 162315078cd4SMichael Lange 162415078cd4SMichael Lange PetscFunctionBegin; 162515078cd4SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 16269566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Migrate, dm, 0, 0, 0)); 16279566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 16289566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 16299566063dSJacob Faibussowitsch PetscCall(DMSetDimension(targetDM, dim)); 16309566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 16319566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(targetDM, cdim)); 163215078cd4SMichael Lange 1633bfb0467fSMichael Lange /* Check for a one-to-all distribution pattern */ 16349566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 16359566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 1636bfb0467fSMichael Lange if (nroots >= 0) { 1637b9f40539SMichael Lange IS isOriginal; 1638ac04eaf7SToby Isaac PetscInt n, size, nleaves; 1639ac04eaf7SToby Isaac PetscInt *numbering_orig, *numbering_new; 1640367003a6SStefano Zampini 1641b9f40539SMichael Lange /* Get the original point numbering */ 16429566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &isOriginal)); 16439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(isOriginal, <ogOriginal)); 16449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(ltogOriginal, &size)); 16459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltogOriginal, (const PetscInt **)&numbering_orig)); 1646b9f40539SMichael Lange /* Convert to positive global numbers */ 16479371c9d4SSatish Balay for (n = 0; n < size; n++) { 16489371c9d4SSatish Balay if (numbering_orig[n] < 0) numbering_orig[n] = -(numbering_orig[n] + 1); 16499371c9d4SSatish Balay } 1650b9f40539SMichael Lange /* Derive the new local-to-global mapping from the old one */ 16519566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, NULL, NULL)); 16529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &numbering_new)); 16539566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, numbering_orig, numbering_new, MPI_REPLACE)); 16549566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, numbering_orig, numbering_new, MPI_REPLACE)); 16559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, nleaves, numbering_new, PETSC_OWN_POINTER, <ogMigration)); 16569566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogOriginal, (const PetscInt **)&numbering_orig)); 16579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isOriginal)); 165815078cd4SMichael Lange } else { 1659bfb0467fSMichael Lange /* One-to-all distribution pattern: We can derive LToG from SF */ 16609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateSF(sf, 0, <ogMigration)); 166115078cd4SMichael Lange } 1662a5a902f7SVaclav Hapla PetscCall(PetscObjectSetName((PetscObject)ltogMigration, "Point renumbering for DM migration")); 1663a5a902f7SVaclav Hapla PetscCall(ISLocalToGlobalMappingViewFromOptions(ltogMigration, (PetscObject)dm, "-partition_view")); 166415078cd4SMichael Lange /* Migrate DM data to target DM */ 16659566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeCones(dm, sf, ltogOriginal, ltogMigration, targetDM)); 16669566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeLabels(dm, sf, targetDM)); 16679566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeCoordinates(dm, sf, targetDM)); 16689566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetupTree(dm, sf, ltogOriginal, ltogMigration, targetDM)); 16699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<ogOriginal)); 16709566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<ogMigration)); 16719566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Migrate, dm, 0, 0, 0)); 16723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 167315078cd4SMichael Lange } 167415078cd4SMichael Lange 167500a1aa47SMatthew G. Knepley /*@ 167600a1aa47SMatthew G. Knepley DMPlexRemapMigrationSF - Rewrite the distribution SF to account for overlap 167700a1aa47SMatthew G. Knepley 167800a1aa47SMatthew G. Knepley Collective 167900a1aa47SMatthew G. Knepley 168000a1aa47SMatthew G. Knepley Input Parameters: 168100a1aa47SMatthew G. Knepley + sfOverlap - The `PetscSF` object just for the overlap 168200a1aa47SMatthew G. Knepley - sfMigration - The original distribution `PetscSF` object 168300a1aa47SMatthew G. Knepley 168400a1aa47SMatthew G. Knepley Output Parameters: 168500a1aa47SMatthew G. Knepley . sfMigrationNew - A rewritten `PetscSF` object that incorporates the overlap 168600a1aa47SMatthew G. Knepley 168700a1aa47SMatthew G. Knepley Level: developer 168800a1aa47SMatthew G. Knepley 168900a1aa47SMatthew G. Knepley .seealso: `DMPLEX`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()`, `DMPlexGetOverlap()` 169000a1aa47SMatthew G. Knepley @*/ 169100a1aa47SMatthew G. Knepley PetscErrorCode DMPlexRemapMigrationSF(PetscSF sfOverlap, PetscSF sfMigration, PetscSF *sfMigrationNew) 169200a1aa47SMatthew G. Knepley { 1693835f2295SStefano Zampini PetscSFNode *newRemote, *permRemote = NULL; 169400a1aa47SMatthew G. Knepley const PetscInt *oldLeaves; 169500a1aa47SMatthew G. Knepley const PetscSFNode *oldRemote; 169600a1aa47SMatthew G. Knepley PetscInt nroots, nleaves, noldleaves; 169700a1aa47SMatthew G. Knepley 169800a1aa47SMatthew G. Knepley PetscFunctionBegin; 169900a1aa47SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfMigration, &nroots, &noldleaves, &oldLeaves, &oldRemote)); 170000a1aa47SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfOverlap, NULL, &nleaves, NULL, NULL)); 170100a1aa47SMatthew G. Knepley PetscCall(PetscMalloc1(nleaves, &newRemote)); 170200a1aa47SMatthew G. Knepley /* oldRemote: original root point mapping to original leaf point 170300a1aa47SMatthew G. Knepley newRemote: original leaf point mapping to overlapped leaf point */ 170400a1aa47SMatthew G. Knepley if (oldLeaves) { 170500a1aa47SMatthew G. Knepley /* After stratification, the migration remotes may not be in root (canonical) order, so we reorder using the leaf numbering */ 170600a1aa47SMatthew G. Knepley PetscCall(PetscMalloc1(noldleaves, &permRemote)); 170700a1aa47SMatthew G. Knepley for (PetscInt l = 0; l < noldleaves; ++l) permRemote[oldLeaves[l]] = oldRemote[l]; 170800a1aa47SMatthew G. Knepley oldRemote = permRemote; 170900a1aa47SMatthew G. Knepley } 17106497c311SBarry Smith PetscCall(PetscSFBcastBegin(sfOverlap, MPIU_SF_NODE, oldRemote, newRemote, MPI_REPLACE)); 17116497c311SBarry Smith PetscCall(PetscSFBcastEnd(sfOverlap, MPIU_SF_NODE, oldRemote, newRemote, MPI_REPLACE)); 1712835f2295SStefano Zampini PetscCall(PetscFree(permRemote)); 171300a1aa47SMatthew G. Knepley PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)sfOverlap), sfMigrationNew)); 171400a1aa47SMatthew G. Knepley PetscCall(PetscSFSetGraph(*sfMigrationNew, nroots, nleaves, NULL, PETSC_OWN_POINTER, newRemote, PETSC_OWN_POINTER)); 171500a1aa47SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 171600a1aa47SMatthew G. Knepley } 171700a1aa47SMatthew G. Knepley 17185d83a8b1SBarry Smith /*@ 171970034214SMatthew G. Knepley DMPlexDistribute - Distributes the mesh and any associated sections. 172070034214SMatthew G. Knepley 172120f4b53cSBarry Smith Collective 172270034214SMatthew G. Knepley 1723064ec1f3Sprj- Input Parameters: 172420f4b53cSBarry Smith + dm - The original `DMPLEX` object 172570034214SMatthew G. Knepley - overlap - The overlap of partitions, 0 is the default 172670034214SMatthew G. Knepley 1727064ec1f3Sprj- Output Parameters: 172820f4b53cSBarry Smith + sf - The `PetscSF` used for point distribution, or `NULL` if not needed 172920f4b53cSBarry Smith - dmParallel - The distributed `DMPLEX` object 173070034214SMatthew G. Knepley 173170034214SMatthew G. Knepley Level: intermediate 173270034214SMatthew G. Knepley 173320f4b53cSBarry Smith Note: 173420f4b53cSBarry Smith If the mesh was not distributed, the output `dmParallel` will be `NULL`. 173520f4b53cSBarry Smith 173620f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function 173720f4b53cSBarry Smith representation on the mesh. 173820f4b53cSBarry Smith 173920f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexGetOverlap()` 174070034214SMatthew G. Knepley @*/ 1741d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistribute(DM dm, PetscInt overlap, PetscSF *sf, DM *dmParallel) 1742d71ae5a4SJacob Faibussowitsch { 174370034214SMatthew G. Knepley MPI_Comm comm; 174415078cd4SMichael Lange PetscPartitioner partitioner; 1745f8987ae8SMichael Lange IS cellPart; 1746f8987ae8SMichael Lange PetscSection cellPartSection; 1747cf86098cSMatthew G. Knepley DM dmCoord; 1748f8987ae8SMichael Lange DMLabel lblPartition, lblMigration; 1749874ddda9SLisandro Dalcin PetscSF sfMigration, sfStratified, sfPoint; 175098ba2d7fSLawrence Mitchell PetscBool flg, balance; 1751874ddda9SLisandro Dalcin PetscMPIInt rank, size; 175270034214SMatthew G. Knepley 175370034214SMatthew G. Knepley PetscFunctionBegin; 175470034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1755d5c515a1SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 2); 17564f572ea9SToby Isaac if (sf) PetscAssertPointer(sf, 3); 17574f572ea9SToby Isaac PetscAssertPointer(dmParallel, 4); 175870034214SMatthew G. Knepley 17590c86c063SLisandro Dalcin if (sf) *sf = NULL; 17600c86c063SLisandro Dalcin *dmParallel = NULL; 17619566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 17629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 17639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 17643ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 176570034214SMatthew G. Knepley 17669566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Distribute, dm, 0, 0, 0)); 176715078cd4SMichael Lange /* Create cell partition */ 17689566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0)); 17699566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &cellPartSection)); 17709566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &partitioner)); 17719566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDMPlexPartition(partitioner, dm, NULL, cellPartSection, &cellPart)); 17729566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartSelf, dm, 0, 0, 0)); 1773f8987ae8SMichael Lange { 1774f8987ae8SMichael Lange /* Convert partition to DMLabel */ 1775825f8a23SLisandro Dalcin IS is; 1776825f8a23SLisandro Dalcin PetscHSetI ht; 1777f8987ae8SMichael Lange const PetscInt *points; 17788e330a33SStefano Zampini PetscInt *iranks; 17798e330a33SStefano Zampini PetscInt pStart, pEnd, proc, npoints, poff = 0, nranks; 1780825f8a23SLisandro Dalcin 17819566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point Partition", &lblPartition)); 1782825f8a23SLisandro Dalcin /* Preallocate strata */ 17839566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 17849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1785825f8a23SLisandro Dalcin for (proc = pStart; proc < pEnd; proc++) { 17869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints)); 17879566063dSJacob Faibussowitsch if (npoints) PetscCall(PetscHSetIAdd(ht, proc)); 1788825f8a23SLisandro Dalcin } 17899566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ht, &nranks)); 17909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nranks, &iranks)); 17919566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ht, &poff, iranks)); 17929566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 17939566063dSJacob Faibussowitsch PetscCall(DMLabelAddStrata(lblPartition, nranks, iranks)); 17949566063dSJacob Faibussowitsch PetscCall(PetscFree(iranks)); 1795825f8a23SLisandro Dalcin /* Inline DMPlexPartitionLabelClosure() */ 17969566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellPart, &points)); 17979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1798f8987ae8SMichael Lange for (proc = pStart; proc < pEnd; proc++) { 17999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints)); 1800825f8a23SLisandro Dalcin if (!npoints) continue; 18019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellPartSection, proc, &poff)); 18029566063dSJacob Faibussowitsch PetscCall(DMPlexClosurePoints_Private(dm, npoints, points + poff, &is)); 18039566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(lblPartition, proc, is)); 18049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1805f8987ae8SMichael Lange } 18069566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellPart, &points)); 1807f8987ae8SMichael Lange } 18089566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartSelf, dm, 0, 0, 0)); 18096e203dd9SStefano Zampini 18109566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point migration", &lblMigration)); 18119566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelInvert(dm, lblPartition, NULL, lblMigration)); 18123ac0285dSStefano Zampini PetscCall(DMPlexPartitionLabelCreateSF(dm, lblMigration, PETSC_TRUE, &sfMigration)); 18139566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, sfMigration, &sfStratified)); 18149566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration)); 181543f7d02bSMichael Lange sfMigration = sfStratified; 18169566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sfMigration)); 18179566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0)); 18189566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-partition_view", &flg)); 181970034214SMatthew G. Knepley if (flg) { 18209566063dSJacob Faibussowitsch PetscCall(DMLabelView(lblPartition, PETSC_VIEWER_STDOUT_(comm))); 18219566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfMigration, PETSC_VIEWER_STDOUT_(comm))); 182270034214SMatthew G. Knepley } 1823f8987ae8SMichael Lange 182415078cd4SMichael Lange /* Create non-overlapping parallel DM and migrate internal data */ 18259566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, dmParallel)); 18269566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*dmParallel, "Parallel Mesh")); 18279566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(dm, sfMigration, *dmParallel)); 182870034214SMatthew G. Knepley 1829a157612eSMichael Lange /* Build the point SF without overlap */ 18309566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitionBalance(dm, &balance)); 18319566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitionBalance(*dmParallel, balance)); 18329566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*dmParallel, sfMigration, PETSC_TRUE, &sfPoint)); 18339566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*dmParallel, sfPoint)); 18345f06a3ddSJed Brown PetscCall(DMPlexMigrateIsoperiodicFaceSF_Internal(dm, *dmParallel, sfMigration)); 18359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dmParallel, &dmCoord)); 18369566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 18379566063dSJacob Faibussowitsch if (flg) PetscCall(PetscSFView(sfPoint, NULL)); 183870034214SMatthew G. Knepley 1839a157612eSMichael Lange if (overlap > 0) { 184015078cd4SMichael Lange DM dmOverlap; 184115078cd4SMichael Lange PetscSF sfOverlap, sfOverlapPoint; 1842524e35f8SStefano Zampini 1843a157612eSMichael Lange /* Add the partition overlap to the distributed DM */ 18449566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeOverlap(*dmParallel, overlap, &sfOverlap, &dmOverlap)); 18459566063dSJacob Faibussowitsch PetscCall(DMDestroy(dmParallel)); 1846a157612eSMichael Lange *dmParallel = dmOverlap; 1847c389ea9fSToby Isaac if (flg) { 18489566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Overlap Migration SF:\n")); 18499566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfOverlap, NULL)); 1850c389ea9fSToby Isaac } 185143331d4aSMichael Lange 1852f8987ae8SMichael Lange /* Re-map the migration SF to establish the full migration pattern */ 185300a1aa47SMatthew G. Knepley PetscCall(DMPlexRemapMigrationSF(sfOverlap, sfMigration, &sfOverlapPoint)); 18549566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfOverlap)); 18559566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration)); 185615078cd4SMichael Lange sfMigration = sfOverlapPoint; 1857c389ea9fSToby Isaac } 1858bf5244c7SMatthew G. Knepley /* Cleanup Partition */ 18599566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblPartition)); 18609566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblMigration)); 18619566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cellPartSection)); 18629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellPart)); 186312a88998SMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *dmParallel)); 186412a88998SMatthew G. Knepley // Create sfNatural, need discretization information 18659566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *dmParallel)); 1866*5d2873a6SJames Wright if (dm->localSection) { 1867*5d2873a6SJames Wright PetscSection psection; 1868*5d2873a6SJames Wright PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &psection)); 1869*5d2873a6SJames Wright PetscCall(PetscSFDistributeSection(sfMigration, dm->localSection, NULL, psection)); 1870*5d2873a6SJames Wright PetscCall(DMSetLocalSection(*dmParallel, psection)); 1871*5d2873a6SJames Wright PetscCall(PetscSectionDestroy(&psection)); 1872*5d2873a6SJames Wright } 187366fe0bfeSMatthew G. Knepley if (dm->useNatural) { 187466fe0bfeSMatthew G. Knepley PetscSection section; 187566fe0bfeSMatthew G. Knepley 1876fc6a3818SBlaise Bourdin PetscCall(DMSetUseNatural(*dmParallel, PETSC_TRUE)); 1877fc6a3818SBlaise Bourdin PetscCall(DMGetLocalSection(dm, §ion)); 1878fc6a3818SBlaise Bourdin 187916635c05SJames Wright /* If DM has useNatural = PETSC_TRUE, but no sfNatural is set, the DM's Section is considered natural */ 18808aee0f92SAlexis Marboeuf /* sfMigration and sfNatural are respectively the point and dofs SFs mapping to this natural DM */ 1881fc6a3818SBlaise Bourdin /* Compose with a previous sfNatural if present */ 1882fc6a3818SBlaise Bourdin if (dm->sfNatural) { 188316635c05SJames Wright PetscCall(DMPlexMigrateGlobalToNaturalSF(dm, *dmParallel, dm->sfNatural, sfMigration, &(*dmParallel)->sfNatural)); 1884fc6a3818SBlaise Bourdin } else { 1885fc6a3818SBlaise Bourdin PetscCall(DMPlexCreateGlobalToNaturalSF(*dmParallel, section, sfMigration, &(*dmParallel)->sfNatural)); 1886fc6a3818SBlaise Bourdin } 18878aee0f92SAlexis Marboeuf /* Compose with a previous sfMigration if present */ 18888aee0f92SAlexis Marboeuf if (dm->sfMigration) { 18898aee0f92SAlexis Marboeuf PetscSF naturalPointSF; 18908aee0f92SAlexis Marboeuf 18918aee0f92SAlexis Marboeuf PetscCall(PetscSFCompose(dm->sfMigration, sfMigration, &naturalPointSF)); 18928aee0f92SAlexis Marboeuf PetscCall(PetscSFDestroy(&sfMigration)); 18938aee0f92SAlexis Marboeuf sfMigration = naturalPointSF; 18948aee0f92SAlexis Marboeuf } 189566fe0bfeSMatthew G. Knepley } 1896721cbd76SMatthew G. Knepley /* Cleanup */ 18979371c9d4SSatish Balay if (sf) { 18989371c9d4SSatish Balay *sf = sfMigration; 18999371c9d4SSatish Balay } else PetscCall(PetscSFDestroy(&sfMigration)); 19009566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 19019566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Distribute, dm, 0, 0, 0)); 19023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 190370034214SMatthew G. Knepley } 1904a157612eSMichael Lange 1905907a3e9cSStefano Zampini PetscErrorCode DMPlexDistributeOverlap_Internal(DM dm, PetscInt overlap, MPI_Comm newcomm, const char *ovlboundary, PetscSF *sf, DM *dmOverlap) 1906907a3e9cSStefano Zampini { 1907907a3e9cSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 1908907a3e9cSStefano Zampini MPI_Comm comm; 1909907a3e9cSStefano Zampini PetscMPIInt size, rank; 1910907a3e9cSStefano Zampini PetscSection rootSection, leafSection; 1911907a3e9cSStefano Zampini IS rootrank, leafrank; 1912907a3e9cSStefano Zampini DM dmCoord; 1913907a3e9cSStefano Zampini DMLabel lblOverlap; 1914907a3e9cSStefano Zampini PetscSF sfOverlap, sfStratified, sfPoint; 1915907a3e9cSStefano Zampini PetscBool clear_ovlboundary; 1916907a3e9cSStefano Zampini 1917907a3e9cSStefano Zampini PetscFunctionBegin; 1918907a3e9cSStefano Zampini if (sf) *sf = NULL; 1919907a3e9cSStefano Zampini *dmOverlap = NULL; 1920907a3e9cSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 1921907a3e9cSStefano Zampini PetscCallMPI(MPI_Comm_size(comm, &size)); 1922907a3e9cSStefano Zampini PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1923907a3e9cSStefano Zampini if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 1924907a3e9cSStefano Zampini { 1925907a3e9cSStefano Zampini // We need to get options for the _already_distributed mesh, so it must be done here 1926907a3e9cSStefano Zampini PetscInt overlap; 1927907a3e9cSStefano Zampini const char *prefix; 1928907a3e9cSStefano Zampini char oldPrefix[PETSC_MAX_PATH_LEN]; 1929907a3e9cSStefano Zampini 1930907a3e9cSStefano Zampini oldPrefix[0] = '\0'; 1931907a3e9cSStefano Zampini PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 1932907a3e9cSStefano Zampini PetscCall(PetscStrncpy(oldPrefix, prefix, sizeof(oldPrefix))); 1933907a3e9cSStefano Zampini PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, "dist_")); 1934907a3e9cSStefano Zampini PetscCall(DMPlexGetOverlap(dm, &overlap)); 1935907a3e9cSStefano Zampini PetscObjectOptionsBegin((PetscObject)dm); 1936907a3e9cSStefano Zampini PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 1937907a3e9cSStefano Zampini PetscOptionsEnd(); 1938907a3e9cSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix[0] == '\0' ? NULL : oldPrefix)); 1939907a3e9cSStefano Zampini } 1940907a3e9cSStefano Zampini if (ovlboundary) { 1941907a3e9cSStefano Zampini PetscBool flg; 1942907a3e9cSStefano Zampini PetscCall(DMHasLabel(dm, ovlboundary, &flg)); 1943907a3e9cSStefano Zampini if (!flg) { 1944907a3e9cSStefano Zampini DMLabel label; 1945907a3e9cSStefano Zampini 1946907a3e9cSStefano Zampini PetscCall(DMCreateLabel(dm, ovlboundary)); 1947907a3e9cSStefano Zampini PetscCall(DMGetLabel(dm, ovlboundary, &label)); 1948907a3e9cSStefano Zampini PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label)); 1949907a3e9cSStefano Zampini clear_ovlboundary = PETSC_TRUE; 1950907a3e9cSStefano Zampini } 1951907a3e9cSStefano Zampini } 1952907a3e9cSStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 1953907a3e9cSStefano Zampini /* Compute point overlap with neighbouring processes on the distributed DM */ 1954907a3e9cSStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0)); 1955907a3e9cSStefano Zampini PetscCall(PetscSectionCreate(newcomm, &rootSection)); 1956907a3e9cSStefano Zampini PetscCall(PetscSectionCreate(newcomm, &leafSection)); 1957907a3e9cSStefano Zampini PetscCall(DMPlexDistributeOwnership(dm, rootSection, &rootrank, leafSection, &leafrank)); 1958907a3e9cSStefano Zampini if (mesh->numOvLabels) PetscCall(DMPlexCreateOverlapLabelFromLabels(dm, mesh->numOvLabels, mesh->ovLabels, mesh->ovValues, mesh->numOvExLabels, mesh->ovExLabels, mesh->ovExValues, rootSection, rootrank, leafSection, leafrank, &lblOverlap)); 1959907a3e9cSStefano Zampini else PetscCall(DMPlexCreateOverlapLabel(dm, overlap, rootSection, rootrank, leafSection, leafrank, &lblOverlap)); 1960907a3e9cSStefano Zampini /* Convert overlap label to stratified migration SF */ 19613ac0285dSStefano Zampini PetscCall(DMPlexPartitionLabelCreateSF(dm, lblOverlap, PETSC_FALSE, &sfOverlap)); 1962907a3e9cSStefano Zampini PetscCall(DMPlexStratifyMigrationSF(dm, sfOverlap, &sfStratified)); 1963907a3e9cSStefano Zampini PetscCall(PetscSFDestroy(&sfOverlap)); 1964907a3e9cSStefano Zampini sfOverlap = sfStratified; 1965907a3e9cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)sfOverlap, "Overlap SF")); 1966907a3e9cSStefano Zampini PetscCall(PetscSFSetFromOptions(sfOverlap)); 1967907a3e9cSStefano Zampini 1968907a3e9cSStefano Zampini PetscCall(PetscSectionDestroy(&rootSection)); 1969907a3e9cSStefano Zampini PetscCall(PetscSectionDestroy(&leafSection)); 1970907a3e9cSStefano Zampini PetscCall(ISDestroy(&rootrank)); 1971907a3e9cSStefano Zampini PetscCall(ISDestroy(&leafrank)); 1972907a3e9cSStefano Zampini PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0)); 1973907a3e9cSStefano Zampini 1974907a3e9cSStefano Zampini /* Build the overlapping DM */ 1975907a3e9cSStefano Zampini PetscCall(DMPlexCreate(newcomm, dmOverlap)); 1976907a3e9cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*dmOverlap, "Parallel Mesh")); 1977907a3e9cSStefano Zampini PetscCall(DMPlexMigrate(dm, sfOverlap, *dmOverlap)); 1978907a3e9cSStefano Zampini /* Store the overlap in the new DM */ 1979907a3e9cSStefano Zampini PetscCall(DMPlexSetOverlap_Plex(*dmOverlap, dm, overlap)); 1980907a3e9cSStefano Zampini /* Build the new point SF */ 1981907a3e9cSStefano Zampini PetscCall(DMPlexCreatePointSF(*dmOverlap, sfOverlap, PETSC_FALSE, &sfPoint)); 1982907a3e9cSStefano Zampini PetscCall(DMSetPointSF(*dmOverlap, sfPoint)); 1983907a3e9cSStefano Zampini PetscCall(DMGetCoordinateDM(*dmOverlap, &dmCoord)); 1984907a3e9cSStefano Zampini if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 1985907a3e9cSStefano Zampini PetscCall(DMGetCellCoordinateDM(*dmOverlap, &dmCoord)); 1986907a3e9cSStefano Zampini if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 1987907a3e9cSStefano Zampini PetscCall(PetscSFDestroy(&sfPoint)); 1988907a3e9cSStefano Zampini PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *dmOverlap)); 1989907a3e9cSStefano Zampini /* TODO: labels stored inside the DS for regions should be handled here */ 1990907a3e9cSStefano Zampini PetscCall(DMCopyDisc(dm, *dmOverlap)); 1991907a3e9cSStefano Zampini /* Cleanup overlap partition */ 1992907a3e9cSStefano Zampini PetscCall(DMLabelDestroy(&lblOverlap)); 1993907a3e9cSStefano Zampini if (sf) *sf = sfOverlap; 1994907a3e9cSStefano Zampini else PetscCall(PetscSFDestroy(&sfOverlap)); 1995907a3e9cSStefano Zampini if (ovlboundary) { 1996907a3e9cSStefano Zampini DMLabel label; 1997907a3e9cSStefano Zampini PetscBool flg; 1998907a3e9cSStefano Zampini 1999907a3e9cSStefano Zampini if (clear_ovlboundary) PetscCall(DMRemoveLabel(dm, ovlboundary, NULL)); 2000907a3e9cSStefano Zampini PetscCall(DMHasLabel(*dmOverlap, ovlboundary, &flg)); 200100045ab3SPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing %s label", ovlboundary); 2002907a3e9cSStefano Zampini PetscCall(DMGetLabel(*dmOverlap, ovlboundary, &label)); 2003907a3e9cSStefano Zampini PetscCall(DMPlexMarkBoundaryFaces_Internal(*dmOverlap, 1, 0, label, PETSC_TRUE)); 2004907a3e9cSStefano Zampini } 2005907a3e9cSStefano Zampini PetscCall(PetscLogEventEnd(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 2006907a3e9cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2007907a3e9cSStefano Zampini } 2008907a3e9cSStefano Zampini 20095d83a8b1SBarry Smith /*@ 201020f4b53cSBarry Smith DMPlexDistributeOverlap - Add partition overlap to a distributed non-overlapping `DM`. 2011a157612eSMichael Lange 201220f4b53cSBarry Smith Collective 2013a157612eSMichael Lange 2014064ec1f3Sprj- Input Parameters: 201520f4b53cSBarry Smith + dm - The non-overlapping distributed `DMPLEX` object 201657fe9a49SVaclav Hapla - overlap - The overlap of partitions (the same on all ranks) 2017a157612eSMichael Lange 2018064ec1f3Sprj- Output Parameters: 2019f13dfd9eSBarry Smith + sf - The `PetscSF` used for point distribution, or pass `NULL` if not needed 2020f13dfd9eSBarry Smith - dmOverlap - The overlapping distributed `DMPLEX` object 2021a157612eSMichael Lange 2022c506a872SMatthew G. Knepley Options Database Keys: 2023c506a872SMatthew G. Knepley + -dm_plex_overlap_labels <name1,name2,...> - List of overlap label names 2024c506a872SMatthew G. Knepley . -dm_plex_overlap_values <int1,int2,...> - List of overlap label values 2025c506a872SMatthew G. Knepley . -dm_plex_overlap_exclude_label <name> - Label used to exclude points from overlap 2026c506a872SMatthew G. Knepley - -dm_plex_overlap_exclude_value <int> - Label value used to exclude points from overlap 2027c506a872SMatthew G. Knepley 2028dccdeccaSVaclav Hapla Level: advanced 2029a157612eSMichael Lange 203020f4b53cSBarry Smith Notes: 203120f4b53cSBarry Smith If the mesh was not distributed, the return value is `NULL`. 203220f4b53cSBarry Smith 203320f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function 203420f4b53cSBarry Smith representation on the mesh. 203520f4b53cSBarry Smith 203620f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMPlexCreateOverlapLabel()`, `DMPlexGetOverlap()` 2037a157612eSMichael Lange @*/ 2038d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeOverlap(DM dm, PetscInt overlap, PetscSF *sf, DM *dmOverlap) 2039d71ae5a4SJacob Faibussowitsch { 2040a157612eSMichael Lange PetscFunctionBegin; 2041a157612eSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 204257fe9a49SVaclav Hapla PetscValidLogicalCollectiveInt(dm, overlap, 2); 20434f572ea9SToby Isaac if (sf) PetscAssertPointer(sf, 3); 20444f572ea9SToby Isaac PetscAssertPointer(dmOverlap, 4); 2045907a3e9cSStefano Zampini PetscCall(DMPlexDistributeOverlap_Internal(dm, overlap, PetscObjectComm((PetscObject)dm), NULL, sf, dmOverlap)); 20463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2047a157612eSMichael Lange } 20486462276dSToby Isaac 2049d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap_Plex(DM dm, PetscInt *overlap) 2050d71ae5a4SJacob Faibussowitsch { 2051cb54e036SVaclav Hapla DM_Plex *mesh = (DM_Plex *)dm->data; 2052cb54e036SVaclav Hapla 2053cb54e036SVaclav Hapla PetscFunctionBegin; 2054cb54e036SVaclav Hapla *overlap = mesh->overlap; 20553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2056cb54e036SVaclav Hapla } 2057cb54e036SVaclav Hapla 2058d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap_Plex(DM dm, DM dmSrc, PetscInt overlap) 2059d71ae5a4SJacob Faibussowitsch { 206060667520SVaclav Hapla DM_Plex *mesh = NULL; 206160667520SVaclav Hapla DM_Plex *meshSrc = NULL; 206260667520SVaclav Hapla 206360667520SVaclav Hapla PetscFunctionBegin; 206460667520SVaclav Hapla PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 206560667520SVaclav Hapla mesh = (DM_Plex *)dm->data; 206660667520SVaclav Hapla if (dmSrc) { 206760667520SVaclav Hapla PetscValidHeaderSpecificType(dmSrc, DM_CLASSID, 2, DMPLEX); 206860667520SVaclav Hapla meshSrc = (DM_Plex *)dmSrc->data; 20699ed9361bSToby Isaac mesh->overlap = meshSrc->overlap; 20709ed9361bSToby Isaac } else { 20719ed9361bSToby Isaac mesh->overlap = 0; 207260667520SVaclav Hapla } 20739ed9361bSToby Isaac mesh->overlap += overlap; 20743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 207560667520SVaclav Hapla } 207660667520SVaclav Hapla 2077cb54e036SVaclav Hapla /*@ 2078c506a872SMatthew G. Knepley DMPlexGetOverlap - Get the width of the cell overlap 2079cb54e036SVaclav Hapla 208020f4b53cSBarry Smith Not Collective 2081cb54e036SVaclav Hapla 2082cb54e036SVaclav Hapla Input Parameter: 208320f4b53cSBarry Smith . dm - The `DM` 2084cb54e036SVaclav Hapla 2085064ec1f3Sprj- Output Parameter: 2086c506a872SMatthew G. Knepley . overlap - the width of the cell overlap 2087cb54e036SVaclav Hapla 2088cb54e036SVaclav Hapla Level: intermediate 2089cb54e036SVaclav Hapla 209020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexSetOverlap()`, `DMPlexDistribute()` 2091cb54e036SVaclav Hapla @*/ 2092d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap(DM dm, PetscInt *overlap) 2093d71ae5a4SJacob Faibussowitsch { 2094cb54e036SVaclav Hapla PetscFunctionBegin; 2095cb54e036SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20964f572ea9SToby Isaac PetscAssertPointer(overlap, 2); 2097cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexGetOverlap_C", (DM, PetscInt *), (dm, overlap)); 20983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2099cb54e036SVaclav Hapla } 2100cb54e036SVaclav Hapla 2101c506a872SMatthew G. Knepley /*@ 2102c506a872SMatthew G. Knepley DMPlexSetOverlap - Set the width of the cell overlap 2103c506a872SMatthew G. Knepley 210420f4b53cSBarry Smith Logically Collective 2105c506a872SMatthew G. Knepley 2106c506a872SMatthew G. Knepley Input Parameters: 210720f4b53cSBarry Smith + dm - The `DM` 210820f4b53cSBarry Smith . dmSrc - The `DM` that produced this one, or `NULL` 2109c506a872SMatthew G. Knepley - overlap - the width of the cell overlap 2110c506a872SMatthew G. Knepley 2111c506a872SMatthew G. Knepley Level: intermediate 2112c506a872SMatthew G. Knepley 211320f4b53cSBarry Smith Note: 211420f4b53cSBarry Smith The overlap from `dmSrc` is added to `dm` 211520f4b53cSBarry Smith 211620f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexGetOverlap()`, `DMPlexDistribute()` 2117c506a872SMatthew G. Knepley @*/ 2118d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap(DM dm, DM dmSrc, PetscInt overlap) 2119d71ae5a4SJacob Faibussowitsch { 2120c506a872SMatthew G. Knepley PetscFunctionBegin; 2121c506a872SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2122c506a872SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 3); 2123c506a872SMatthew G. Knepley PetscTryMethod(dm, "DMPlexSetOverlap_C", (DM, DM, PetscInt), (dm, dmSrc, overlap)); 21243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2125c506a872SMatthew G. Knepley } 2126c506a872SMatthew G. Knepley 2127d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault_Plex(DM dm, PetscBool dist) 2128d71ae5a4SJacob Faibussowitsch { 2129e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2130e600fa54SMatthew G. Knepley 2131e600fa54SMatthew G. Knepley PetscFunctionBegin; 2132e600fa54SMatthew G. Knepley mesh->distDefault = dist; 21333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2134e600fa54SMatthew G. Knepley } 2135e600fa54SMatthew G. Knepley 2136e600fa54SMatthew G. Knepley /*@ 213720f4b53cSBarry Smith DMPlexDistributeSetDefault - Set flag indicating whether the `DM` should be distributed by default 2138e600fa54SMatthew G. Knepley 213920f4b53cSBarry Smith Logically Collective 2140e600fa54SMatthew G. Knepley 2141e600fa54SMatthew G. Knepley Input Parameters: 214220f4b53cSBarry Smith + dm - The `DM` 2143e600fa54SMatthew G. Knepley - dist - Flag for distribution 2144e600fa54SMatthew G. Knepley 2145e600fa54SMatthew G. Knepley Level: intermediate 2146e600fa54SMatthew G. Knepley 214720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributeGetDefault()`, `DMPlexDistribute()` 2148e600fa54SMatthew G. Knepley @*/ 2149d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault(DM dm, PetscBool dist) 2150d71ae5a4SJacob Faibussowitsch { 2151e600fa54SMatthew G. Knepley PetscFunctionBegin; 2152e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2153e600fa54SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, dist, 2); 2154cac4c232SBarry Smith PetscTryMethod(dm, "DMPlexDistributeSetDefault_C", (DM, PetscBool), (dm, dist)); 21553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2156e600fa54SMatthew G. Knepley } 2157e600fa54SMatthew G. Knepley 2158d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault_Plex(DM dm, PetscBool *dist) 2159d71ae5a4SJacob Faibussowitsch { 2160e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2161e600fa54SMatthew G. Knepley 2162e600fa54SMatthew G. Knepley PetscFunctionBegin; 2163e600fa54SMatthew G. Knepley *dist = mesh->distDefault; 21643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2165e600fa54SMatthew G. Knepley } 2166e600fa54SMatthew G. Knepley 2167e600fa54SMatthew G. Knepley /*@ 216820f4b53cSBarry Smith DMPlexDistributeGetDefault - Get flag indicating whether the `DM` should be distributed by default 2169e600fa54SMatthew G. Knepley 217020f4b53cSBarry Smith Not Collective 2171e600fa54SMatthew G. Knepley 2172e600fa54SMatthew G. Knepley Input Parameter: 217320f4b53cSBarry Smith . dm - The `DM` 2174e600fa54SMatthew G. Knepley 2175e600fa54SMatthew G. Knepley Output Parameter: 2176e600fa54SMatthew G. Knepley . dist - Flag for distribution 2177e600fa54SMatthew G. Knepley 2178e600fa54SMatthew G. Knepley Level: intermediate 2179e600fa54SMatthew G. Knepley 218020f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexDistributeSetDefault()`, `DMPlexDistribute()` 2181e600fa54SMatthew G. Knepley @*/ 2182d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault(DM dm, PetscBool *dist) 2183d71ae5a4SJacob Faibussowitsch { 2184e600fa54SMatthew G. Knepley PetscFunctionBegin; 2185e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21864f572ea9SToby Isaac PetscAssertPointer(dist, 2); 2187cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexDistributeGetDefault_C", (DM, PetscBool *), (dm, dist)); 21883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2189e600fa54SMatthew G. Knepley } 2190e600fa54SMatthew G. Knepley 21916462276dSToby Isaac /*@C 219220f4b53cSBarry Smith DMPlexGetGatherDM - Get a copy of the `DMPLEX` that gathers all points on the 21936462276dSToby Isaac root process of the original's communicator. 21946462276dSToby Isaac 219520f4b53cSBarry Smith Collective 219683655b49SVáclav Hapla 2197064ec1f3Sprj- Input Parameter: 219820f4b53cSBarry Smith . dm - the original `DMPLEX` object 21996462276dSToby Isaac 22006462276dSToby Isaac Output Parameters: 220120f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional) 220220f4b53cSBarry Smith - gatherMesh - the gathered `DM` object, or `NULL` 22036462276dSToby Isaac 22046462276dSToby Isaac Level: intermediate 22056462276dSToby Isaac 220620f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `PetscSF`, `DMPlexDistribute()`, `DMPlexGetRedundantDM()` 22076462276dSToby Isaac @*/ 2208d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetGatherDM(DM dm, PetscSF *sf, DM *gatherMesh) 2209d71ae5a4SJacob Faibussowitsch { 22106462276dSToby Isaac MPI_Comm comm; 22116462276dSToby Isaac PetscMPIInt size; 22126462276dSToby Isaac PetscPartitioner oldPart, gatherPart; 22136462276dSToby Isaac 22146462276dSToby Isaac PetscFunctionBegin; 22156462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22164f572ea9SToby Isaac PetscAssertPointer(gatherMesh, 3); 22170c86c063SLisandro Dalcin *gatherMesh = NULL; 2218a13df41bSStefano Zampini if (sf) *sf = NULL; 22196462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 22209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 22213ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 22229566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &oldPart)); 22239566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)oldPart)); 22249566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(comm, &gatherPart)); 22259566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetType(gatherPart, PETSCPARTITIONERGATHER)); 22269566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, gatherPart)); 22279566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, sf, gatherMesh)); 2228a13df41bSStefano Zampini 22299566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, oldPart)); 22309566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&gatherPart)); 22319566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&oldPart)); 22323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22336462276dSToby Isaac } 22346462276dSToby Isaac 22356462276dSToby Isaac /*@C 223620f4b53cSBarry Smith DMPlexGetRedundantDM - Get a copy of the `DMPLEX` that is completely copied on each process. 22376462276dSToby Isaac 223820f4b53cSBarry Smith Collective 223983655b49SVáclav Hapla 2240064ec1f3Sprj- Input Parameter: 224120f4b53cSBarry Smith . dm - the original `DMPLEX` object 22426462276dSToby Isaac 22436462276dSToby Isaac Output Parameters: 224420f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional) 224520f4b53cSBarry Smith - redundantMesh - the redundant `DM` object, or `NULL` 22466462276dSToby Isaac 22476462276dSToby Isaac Level: intermediate 22486462276dSToby Isaac 224960225df5SJacob Faibussowitsch .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetGatherDM()` 22506462276dSToby Isaac @*/ 2251d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRedundantDM(DM dm, PetscSF *sf, DM *redundantMesh) 2252d71ae5a4SJacob Faibussowitsch { 22536462276dSToby Isaac MPI_Comm comm; 22546462276dSToby Isaac PetscMPIInt size, rank; 22556462276dSToby Isaac PetscInt pStart, pEnd, p; 22566462276dSToby Isaac PetscInt numPoints = -1; 2257a13df41bSStefano Zampini PetscSF migrationSF, sfPoint, gatherSF; 22586462276dSToby Isaac DM gatherDM, dmCoord; 22596462276dSToby Isaac PetscSFNode *points; 22606462276dSToby Isaac 22616462276dSToby Isaac PetscFunctionBegin; 22626462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22634f572ea9SToby Isaac PetscAssertPointer(redundantMesh, 3); 22640c86c063SLisandro Dalcin *redundantMesh = NULL; 22656462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 22669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 226768dbc166SMatthew G. Knepley if (size == 1) { 22689566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 226968dbc166SMatthew G. Knepley *redundantMesh = dm; 2270a13df41bSStefano Zampini if (sf) *sf = NULL; 22713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 227268dbc166SMatthew G. Knepley } 22739566063dSJacob Faibussowitsch PetscCall(DMPlexGetGatherDM(dm, &gatherSF, &gatherDM)); 22743ba16761SJacob Faibussowitsch if (!gatherDM) PetscFunctionReturn(PETSC_SUCCESS); 22759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 22769566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(gatherDM, &pStart, &pEnd)); 22776462276dSToby Isaac numPoints = pEnd - pStart; 22789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numPoints, 1, MPIU_INT, 0, comm)); 22799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &points)); 22809566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &migrationSF)); 22816462276dSToby Isaac for (p = 0; p < numPoints; p++) { 22826462276dSToby Isaac points[p].index = p; 22836462276dSToby Isaac points[p].rank = 0; 22846462276dSToby Isaac } 22859566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(migrationSF, pEnd - pStart, numPoints, NULL, PETSC_OWN_POINTER, points, PETSC_OWN_POINTER)); 22869566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, redundantMesh)); 22879566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*redundantMesh, "Redundant Mesh")); 22889566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(gatherDM, migrationSF, *redundantMesh)); 22892e28cf0cSVaclav Hapla /* This is to express that all point are in overlap */ 22901690c2aeSBarry Smith PetscCall(DMPlexSetOverlap_Plex(*redundantMesh, NULL, PETSC_INT_MAX)); 22919566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*redundantMesh, migrationSF, PETSC_FALSE, &sfPoint)); 22929566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*redundantMesh, sfPoint)); 22939566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*redundantMesh, &dmCoord)); 22949566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 22959566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 2296a13df41bSStefano Zampini if (sf) { 2297a13df41bSStefano Zampini PetscSF tsf; 2298a13df41bSStefano Zampini 22999566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(gatherSF, migrationSF, &tsf)); 23009566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, tsf, sf)); 23019566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&tsf)); 2302a13df41bSStefano Zampini } 23039566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&migrationSF)); 23049566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&gatherSF)); 23059566063dSJacob Faibussowitsch PetscCall(DMDestroy(&gatherDM)); 23069566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *redundantMesh)); 23075de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *redundantMesh)); 23083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23096462276dSToby Isaac } 23105fa78c88SVaclav Hapla 23115fa78c88SVaclav Hapla /*@ 231220f4b53cSBarry Smith DMPlexIsDistributed - Find out whether this `DM` is distributed, i.e. more than one rank owns some points. 23135fa78c88SVaclav Hapla 23145fa78c88SVaclav Hapla Collective 23155fa78c88SVaclav Hapla 23165fa78c88SVaclav Hapla Input Parameter: 231720f4b53cSBarry Smith . dm - The `DM` object 23185fa78c88SVaclav Hapla 23195fa78c88SVaclav Hapla Output Parameter: 232020f4b53cSBarry Smith . distributed - Flag whether the `DM` is distributed 23215fa78c88SVaclav Hapla 23225fa78c88SVaclav Hapla Level: intermediate 23235fa78c88SVaclav Hapla 23245fa78c88SVaclav Hapla Notes: 23255fa78c88SVaclav Hapla This currently finds out whether at least two ranks have any DAG points. 232620f4b53cSBarry Smith This involves `MPI_Allreduce()` with one integer. 23275fa78c88SVaclav Hapla The result is currently not stashed so every call to this routine involves this global communication. 23285fa78c88SVaclav Hapla 232960225df5SJacob Faibussowitsch .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetOverlap()`, `DMPlexIsInterpolated()` 23305fa78c88SVaclav Hapla @*/ 2331d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsDistributed(DM dm, PetscBool *distributed) 2332d71ae5a4SJacob Faibussowitsch { 23335fa78c88SVaclav Hapla PetscInt pStart, pEnd, count; 23345fa78c88SVaclav Hapla MPI_Comm comm; 233535d70e31SStefano Zampini PetscMPIInt size; 23365fa78c88SVaclav Hapla 23375fa78c88SVaclav Hapla PetscFunctionBegin; 23385fa78c88SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23394f572ea9SToby Isaac PetscAssertPointer(distributed, 2); 23409566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 23419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 23429371c9d4SSatish Balay if (size == 1) { 23439371c9d4SSatish Balay *distributed = PETSC_FALSE; 23443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23459371c9d4SSatish Balay } 23469566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 234735d70e31SStefano Zampini count = (pEnd - pStart) > 0 ? 1 : 0; 2348462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &count, 1, MPIU_INT, MPI_SUM, comm)); 23495fa78c88SVaclav Hapla *distributed = count > 1 ? PETSC_TRUE : PETSC_FALSE; 23503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23515fa78c88SVaclav Hapla } 23521d1f2f2aSksagiyam 2353cc4c1da9SBarry Smith /*@ 23541d1f2f2aSksagiyam DMPlexDistributionSetName - Set the name of the specific parallel distribution 23551d1f2f2aSksagiyam 23561d1f2f2aSksagiyam Input Parameters: 235720f4b53cSBarry Smith + dm - The `DM` 23581d1f2f2aSksagiyam - name - The name of the specific parallel distribution 23591d1f2f2aSksagiyam 23601d1f2f2aSksagiyam Level: developer 23611d1f2f2aSksagiyam 236220f4b53cSBarry Smith Note: 236320f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's 236420f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under 236520f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()` 236620f4b53cSBarry Smith loads the parallel distribution stored in file under this name. 236720f4b53cSBarry Smith 236820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionGetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()` 23691d1f2f2aSksagiyam @*/ 2370d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionSetName(DM dm, const char name[]) 2371d71ae5a4SJacob Faibussowitsch { 23721d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data; 23731d1f2f2aSksagiyam 23741d1f2f2aSksagiyam PetscFunctionBegin; 23751d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 23764f572ea9SToby Isaac if (name) PetscAssertPointer(name, 2); 23771d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 23781d1f2f2aSksagiyam PetscCall(PetscStrallocpy(name, &mesh->distributionName)); 23793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23801d1f2f2aSksagiyam } 23811d1f2f2aSksagiyam 2382cc4c1da9SBarry Smith /*@ 23831d1f2f2aSksagiyam DMPlexDistributionGetName - Retrieve the name of the specific parallel distribution 23841d1f2f2aSksagiyam 23851d1f2f2aSksagiyam Input Parameter: 238620f4b53cSBarry Smith . dm - The `DM` 23871d1f2f2aSksagiyam 23881d1f2f2aSksagiyam Output Parameter: 23891d1f2f2aSksagiyam . name - The name of the specific parallel distribution 23901d1f2f2aSksagiyam 23911d1f2f2aSksagiyam Level: developer 23921d1f2f2aSksagiyam 239320f4b53cSBarry Smith Note: 239420f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's 239520f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under 239620f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()` 239720f4b53cSBarry Smith loads the parallel distribution stored in file under this name. 239820f4b53cSBarry Smith 239920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionSetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()` 24001d1f2f2aSksagiyam @*/ 2401d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionGetName(DM dm, const char *name[]) 2402d71ae5a4SJacob Faibussowitsch { 24031d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data; 24041d1f2f2aSksagiyam 24051d1f2f2aSksagiyam PetscFunctionBegin; 24061d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 24074f572ea9SToby Isaac PetscAssertPointer(name, 2); 24081d1f2f2aSksagiyam *name = mesh->distributionName; 24093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24101d1f2f2aSksagiyam } 2411