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 73524cc2ca5SMatthew G. Knepley /*@C 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)); 8801c2dc1cbSBarry Smith PetscCall(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 } 9019566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_2INT, pointDepths, remoteDepths, MPI_REPLACE)); 9029566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_2INT, 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 PetscInt dep = remoteDepths[p].index; 951412e9a14SMatthew G. Knepley const DMPolytopeType ct = (DMPolytopeType)remoteDepths[p].rank; 9527fab53ddSMatthew G. Knepley 953412e9a14SMatthew G. Knepley if ((PetscInt)ct < 0) { 9547fab53ddSMatthew G. Knepley ilocal[p] = depthShift[dep] + depthIdx[dep]; 955412e9a14SMatthew G. Knepley ++depthIdx[dep]; 956412e9a14SMatthew G. Knepley } else { 957412e9a14SMatthew G. Knepley ilocal[p] = ctShift[ct] + ctIdx[ct]; 958412e9a14SMatthew G. Knepley ++ctIdx[ct]; 959412e9a14SMatthew G. Knepley } 960a9f1d5b2SMichael Lange } 9619566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, migrationSF)); 9629566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*migrationSF, "Migration SF")); 9639566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*migrationSF, nroots, nleaves, ilocal, PETSC_OWN_POINTER, (PetscSFNode *)iremote, PETSC_COPY_VALUES)); 9649566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointDepths, remoteDepths)); 9659566063dSJacob Faibussowitsch PetscCall(PetscFree6(depthRecv, depthShift, depthIdx, ctRecv, ctShift, ctIdx)); 9669566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartStratSF, dm, 0, 0, 0)); 9673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 968a9f1d5b2SMichael Lange } 969a9f1d5b2SMichael Lange 97070034214SMatthew G. Knepley /*@ 97120f4b53cSBarry Smith DMPlexDistributeField - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 97270034214SMatthew G. Knepley 97320f4b53cSBarry Smith Collective 97470034214SMatthew G. Knepley 97570034214SMatthew G. Knepley Input Parameters: 97620f4b53cSBarry Smith + dm - The `DMPLEX` object 97720f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 97820f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 979cb15cd0eSMatthew G. Knepley - originalVec - The existing data in a local vector 98070034214SMatthew G. Knepley 98170034214SMatthew G. Knepley Output Parameters: 98220f4b53cSBarry Smith + newSection - The `PetscSF` describing the new data layout 983cb15cd0eSMatthew G. Knepley - newVec - The new data in a local vector 98470034214SMatthew G. Knepley 98570034214SMatthew G. Knepley Level: developer 98670034214SMatthew G. Knepley 98720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeFieldIS()`, `DMPlexDistributeData()` 98870034214SMatthew G. Knepley @*/ 989d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 990d71ae5a4SJacob Faibussowitsch { 99170034214SMatthew G. Knepley PetscSF fieldSF; 99270034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize; 99370034214SMatthew G. Knepley PetscScalar *originalValues, *newValues; 99470034214SMatthew G. Knepley 99570034214SMatthew G. Knepley PetscFunctionBegin; 9969566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeField, dm, 0, 0, 0)); 9979566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 99870034214SMatthew G. Knepley 9999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 10009566063dSJacob Faibussowitsch PetscCall(VecSetSizes(newVec, fieldSize, PETSC_DETERMINE)); 10019566063dSJacob Faibussowitsch PetscCall(VecSetType(newVec, dm->vectype)); 100270034214SMatthew G. Knepley 10039566063dSJacob Faibussowitsch PetscCall(VecGetArray(originalVec, &originalValues)); 10049566063dSJacob Faibussowitsch PetscCall(VecGetArray(newVec, &newValues)); 10059566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 10069566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 10079566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues, MPI_REPLACE)); 10089566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues, MPI_REPLACE)); 10099566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 10109566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(newVec, &newValues)); 10119566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(originalVec, &originalValues)); 10129566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeField, dm, 0, 0, 0)); 10133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 101470034214SMatthew G. Knepley } 101570034214SMatthew G. Knepley 101670034214SMatthew G. Knepley /*@ 101720f4b53cSBarry Smith DMPlexDistributeFieldIS - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 101870034214SMatthew G. Knepley 101920f4b53cSBarry Smith Collective 102070034214SMatthew G. Knepley 102170034214SMatthew G. Knepley Input Parameters: 102220f4b53cSBarry Smith + dm - The `DMPLEX` object 102320f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 102420f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 102570034214SMatthew G. Knepley - originalIS - The existing data 102670034214SMatthew G. Knepley 102770034214SMatthew G. Knepley Output Parameters: 102820f4b53cSBarry Smith + newSection - The `PetscSF` describing the new data layout 102970034214SMatthew G. Knepley - newIS - The new data 103070034214SMatthew G. Knepley 103170034214SMatthew G. Knepley Level: developer 103270034214SMatthew G. Knepley 103320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexDistributeData()` 103470034214SMatthew G. Knepley @*/ 1035d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeFieldIS(DM dm, PetscSF pointSF, PetscSection originalSection, IS originalIS, PetscSection newSection, IS *newIS) 1036d71ae5a4SJacob Faibussowitsch { 103770034214SMatthew G. Knepley PetscSF fieldSF; 103870034214SMatthew G. Knepley PetscInt *newValues, *remoteOffsets, fieldSize; 103970034214SMatthew G. Knepley const PetscInt *originalValues; 104070034214SMatthew G. Knepley 104170034214SMatthew G. Knepley PetscFunctionBegin; 10429566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeField, dm, 0, 0, 0)); 10439566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 104470034214SMatthew G. Knepley 10459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 10469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(fieldSize, &newValues)); 104770034214SMatthew G. Knepley 10489566063dSJacob Faibussowitsch PetscCall(ISGetIndices(originalIS, &originalValues)); 10499566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 10509566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 10519566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, MPIU_INT, (PetscInt *)originalValues, newValues, MPI_REPLACE)); 10529566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, MPIU_INT, (PetscInt *)originalValues, newValues, MPI_REPLACE)); 10539566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 10549566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(originalIS, &originalValues)); 10559566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pointSF), fieldSize, newValues, PETSC_OWN_POINTER, newIS)); 10569566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeField, dm, 0, 0, 0)); 10573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 105870034214SMatthew G. Knepley } 105970034214SMatthew G. Knepley 106070034214SMatthew G. Knepley /*@ 106120f4b53cSBarry Smith DMPlexDistributeData - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 106270034214SMatthew G. Knepley 106320f4b53cSBarry Smith Collective 106470034214SMatthew G. Knepley 106570034214SMatthew G. Knepley Input Parameters: 106620f4b53cSBarry Smith + dm - The `DMPLEX` object 106720f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 106820f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 106970034214SMatthew G. Knepley . datatype - The type of data 107070034214SMatthew G. Knepley - originalData - The existing data 107170034214SMatthew G. Knepley 107270034214SMatthew G. Knepley Output Parameters: 107320f4b53cSBarry Smith + newSection - The `PetscSection` describing the new data layout 107470034214SMatthew G. Knepley - newData - The new data 107570034214SMatthew G. Knepley 107670034214SMatthew G. Knepley Level: developer 107770034214SMatthew G. Knepley 107820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeField()` 107970034214SMatthew G. Knepley @*/ 1080d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeData(DM dm, PetscSF pointSF, PetscSection originalSection, MPI_Datatype datatype, void *originalData, PetscSection newSection, void **newData) 1081d71ae5a4SJacob Faibussowitsch { 108270034214SMatthew G. Knepley PetscSF fieldSF; 108370034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize; 108470034214SMatthew G. Knepley PetscMPIInt dataSize; 108570034214SMatthew G. Knepley 108670034214SMatthew G. Knepley PetscFunctionBegin; 10879566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeData, dm, 0, 0, 0)); 10889566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 108970034214SMatthew G. Knepley 10909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 10919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_size(datatype, &dataSize)); 10929566063dSJacob Faibussowitsch PetscCall(PetscMalloc(fieldSize * dataSize, newData)); 109370034214SMatthew G. Knepley 10949566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 10959566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 10969566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, datatype, originalData, *newData, MPI_REPLACE)); 10979566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, datatype, originalData, *newData, MPI_REPLACE)); 10989566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 10999566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeData, dm, 0, 0, 0)); 11003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 110170034214SMatthew G. Knepley } 110270034214SMatthew G. Knepley 1103d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeCones(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel) 1104d71ae5a4SJacob Faibussowitsch { 1105cc71bff1SMichael Lange DM_Plex *pmesh = (DM_Plex *)(dmParallel)->data; 1106cc71bff1SMichael Lange MPI_Comm comm; 1107cc71bff1SMichael Lange PetscSF coneSF; 1108cc71bff1SMichael Lange PetscSection originalConeSection, newConeSection; 1109ac04eaf7SToby Isaac PetscInt *remoteOffsets, *cones, *globCones, *newCones, newConesSize; 1110cc71bff1SMichael Lange PetscBool flg; 1111cc71bff1SMichael Lange 1112cc71bff1SMichael Lange PetscFunctionBegin; 1113cc71bff1SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 11140c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5); 11159566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeCones, dm, 0, 0, 0)); 1116cc71bff1SMichael Lange /* Distribute cone section */ 11179566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 11189566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &originalConeSection)); 11199566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dmParallel, &newConeSection)); 11209566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(migrationSF, originalConeSection, &remoteOffsets, newConeSection)); 11219566063dSJacob Faibussowitsch PetscCall(DMSetUp(dmParallel)); 1122cc71bff1SMichael Lange /* Communicate and renumber cones */ 11239566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(migrationSF, originalConeSection, remoteOffsets, newConeSection, &coneSF)); 11249566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 11259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 1126ac04eaf7SToby Isaac if (original) { 1127ac04eaf7SToby Isaac PetscInt numCones; 1128ac04eaf7SToby Isaac 11299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(originalConeSection, &numCones)); 11309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCones, &globCones)); 11319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(original, numCones, cones, globCones)); 1132367003a6SStefano Zampini } else { 1133ac04eaf7SToby Isaac globCones = cones; 1134ac04eaf7SToby Isaac } 11359566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dmParallel, &newCones)); 11369566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coneSF, MPIU_INT, globCones, newCones, MPI_REPLACE)); 11379566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coneSF, MPIU_INT, globCones, newCones, MPI_REPLACE)); 11381baa6e33SBarry Smith if (original) PetscCall(PetscFree(globCones)); 11399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newConeSection, &newConesSize)); 11409566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones)); 114176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 11423533c52bSMatthew G. Knepley PetscInt p; 11433533c52bSMatthew G. Knepley PetscBool valid = PETSC_TRUE; 11443533c52bSMatthew G. Knepley for (p = 0; p < newConesSize; ++p) { 11459371c9d4SSatish Balay if (newCones[p] < 0) { 11469371c9d4SSatish Balay valid = PETSC_FALSE; 11479371c9d4SSatish Balay PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Point %" PetscInt_FMT " not in overlap SF\n", PetscGlobalRank, p)); 11489371c9d4SSatish Balay } 11493533c52bSMatthew G. Knepley } 115028b400f6SJacob Faibussowitsch PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map"); 11513533c52bSMatthew G. Knepley } 11529566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-cones_view", &flg)); 1153cc71bff1SMichael Lange if (flg) { 11549566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Serial Cone Section:\n")); 11559566063dSJacob Faibussowitsch PetscCall(PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_(comm))); 11569566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Parallel Cone Section:\n")); 11579566063dSJacob Faibussowitsch PetscCall(PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_(comm))); 11589566063dSJacob Faibussowitsch PetscCall(PetscSFView(coneSF, NULL)); 1159cc71bff1SMichael Lange } 11609566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dm, &cones)); 11619566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dmParallel, &newCones)); 11629566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones, MPI_REPLACE)); 11639566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones, MPI_REPLACE)); 11649566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coneSF)); 11659566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeCones, dm, 0, 0, 0)); 1166eaf898f9SPatrick Sanan /* Create supports and stratify DMPlex */ 1167cc71bff1SMichael Lange { 1168cc71bff1SMichael Lange PetscInt pStart, pEnd; 1169cc71bff1SMichael Lange 11709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd)); 11719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(pmesh->supportSection, pStart, pEnd)); 1172cc71bff1SMichael Lange } 11739566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dmParallel)); 11749566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dmParallel)); 11751cf84007SMatthew G. Knepley { 11761cf84007SMatthew G. Knepley PetscBool useCone, useClosure, useAnchors; 11771cf84007SMatthew G. Knepley 11789566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 11799566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dmParallel, useCone, useClosure)); 11809566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors)); 11819566063dSJacob Faibussowitsch PetscCall(DMPlexSetAdjacencyUseAnchors(dmParallel, useAnchors)); 11821cf84007SMatthew G. Knepley } 11833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1184cc71bff1SMichael Lange } 1185cc71bff1SMichael Lange 1186d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeCoordinates(DM dm, PetscSF migrationSF, DM dmParallel) 1187d71ae5a4SJacob Faibussowitsch { 11880df0e737SMichael Lange MPI_Comm comm; 11899318fe57SMatthew G. Knepley DM cdm, cdmParallel; 11900df0e737SMichael Lange PetscSection originalCoordSection, newCoordSection; 11910df0e737SMichael Lange Vec originalCoordinates, newCoordinates; 11920df0e737SMichael Lange PetscInt bs; 11930df0e737SMichael Lange const char *name; 11944fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 11950df0e737SMichael Lange 11960df0e737SMichael Lange PetscFunctionBegin; 11970df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 11980c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3); 11990df0e737SMichael Lange 12009566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12016858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 12026858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dmParallel, &cdmParallel)); 12036858538eSMatthew G. Knepley PetscCall(DMCopyDisc(cdm, cdmParallel)); 12049566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &originalCoordSection)); 12059566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmParallel, &newCoordSection)); 12069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &originalCoordinates)); 12070df0e737SMichael Lange if (originalCoordinates) { 12089566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates)); 12099566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalCoordinates, &name)); 12109566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)newCoordinates, name)); 12110df0e737SMichael Lange 12129566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates)); 12139566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmParallel, newCoordinates)); 12149566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(originalCoordinates, &bs)); 12159566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(newCoordinates, bs)); 12169566063dSJacob Faibussowitsch PetscCall(VecDestroy(&newCoordinates)); 12170df0e737SMichael Lange } 12186858538eSMatthew G. Knepley 12196858538eSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12204fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L)); 12214fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmParallel, maxCell, Lstart, L)); 12226858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdm)); 12236858538eSMatthew G. Knepley if (cdm) { 12246858538eSMatthew G. Knepley PetscCall(DMClone(dmParallel, &cdmParallel)); 12256858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmParallel, cdmParallel)); 12269566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(cdm, cdmParallel)); 12276858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmParallel)); 12286858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &originalCoordSection)); 12296858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &originalCoordinates)); 12306858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(comm, &newCoordSection)); 12316858538eSMatthew G. Knepley if (originalCoordinates) { 12326858538eSMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates)); 12336858538eSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)originalCoordinates, &name)); 12346858538eSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)newCoordinates, name)); 12356858538eSMatthew G. Knepley 12366858538eSMatthew G. Knepley PetscCall(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates)); 12376858538eSMatthew G. Knepley PetscCall(VecGetBlockSize(originalCoordinates, &bs)); 12386858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(newCoordinates, bs)); 12396858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(dmParallel, bs, newCoordSection)); 12406858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmParallel, newCoordinates)); 12416858538eSMatthew G. Knepley PetscCall(VecDestroy(&newCoordinates)); 12426858538eSMatthew G. Knepley } 12436858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&newCoordSection)); 12446858538eSMatthew G. Knepley } 12453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12460df0e737SMichael Lange } 12470df0e737SMichael Lange 1248d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeLabels(DM dm, PetscSF migrationSF, DM dmParallel) 1249d71ae5a4SJacob Faibussowitsch { 1250df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 12510df0e737SMichael Lange MPI_Comm comm; 12527980c9d4SMatthew G. Knepley DMLabel depthLabel; 12530df0e737SMichael Lange PetscMPIInt rank; 12547980c9d4SMatthew G. Knepley PetscInt depth, d, numLabels, numLocalLabels, l; 1255df0420ecSMatthew G. Knepley PetscBool hasLabels = PETSC_FALSE, lsendDepth, sendDepth; 1256df0420ecSMatthew G. Knepley PetscObjectState depthState = -1; 12570df0e737SMichael Lange 12580df0e737SMichael Lange PetscFunctionBegin; 12590df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 12600c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3); 12610c86c063SLisandro Dalcin 12629566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeLabels, dm, 0, 0, 0)); 12639566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 12650df0e737SMichael Lange 1266df0420ecSMatthew G. Knepley /* If the user has changed the depth label, communicate it instead */ 12679566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 12689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 12699566063dSJacob Faibussowitsch if (depthLabel) PetscCall(PetscObjectStateGet((PetscObject)depthLabel, &depthState)); 1270df0420ecSMatthew G. Knepley lsendDepth = mesh->depthState != depthState ? PETSC_TRUE : PETSC_FALSE; 12711c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lsendDepth, &sendDepth, 1, MPIU_BOOL, MPI_LOR, comm)); 1272df0420ecSMatthew G. Knepley if (sendDepth) { 12739566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dmParallel, &dmParallel->depthLabel)); 12749566063dSJacob Faibussowitsch PetscCall(DMRemoveLabelBySelf(dmParallel, &dmParallel->depthLabel, PETSC_FALSE)); 1275df0420ecSMatthew G. Knepley } 1276d995df53SMatthew G. Knepley /* Everyone must have either the same number of labels, or none */ 12779566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLocalLabels)); 1278d995df53SMatthew G. Knepley numLabels = numLocalLabels; 12799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm)); 1280627847f0SMatthew G. Knepley if (numLabels == numLocalLabels) hasLabels = PETSC_TRUE; 12815d80c0bfSVaclav Hapla for (l = 0; l < numLabels; ++l) { 1282bdd2d751SMichael Lange DMLabel label = NULL, labelNew = NULL; 128383e10cb3SLisandro Dalcin PetscBool isDepth, lisOutput = PETSC_TRUE, isOutput; 1284d67d17b1SMatthew G. Knepley const char *name = NULL; 12850df0e737SMichael Lange 1286d67d17b1SMatthew G. Knepley if (hasLabels) { 12879566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(dm, l, &label)); 12880df0e737SMichael Lange /* Skip "depth" because it is recreated */ 12899566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)label, &name)); 12909566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 1291bbcf679cSJacob Faibussowitsch } else { 1292bbcf679cSJacob Faibussowitsch isDepth = PETSC_FALSE; 1293d67d17b1SMatthew G. Knepley } 12949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&isDepth, 1, MPIU_BOOL, 0, comm)); 129583e10cb3SLisandro Dalcin if (isDepth && !sendDepth) continue; 12969566063dSJacob Faibussowitsch PetscCall(DMLabelDistribute(label, migrationSF, &labelNew)); 129783e10cb3SLisandro Dalcin if (isDepth) { 12987980c9d4SMatthew G. Knepley /* Put in any missing strata which can occur if users are managing the depth label themselves */ 12997980c9d4SMatthew G. Knepley PetscInt gdepth; 13007980c9d4SMatthew G. Knepley 13011c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&depth, &gdepth, 1, MPIU_INT, MPI_MAX, comm)); 130263a3b9bcSJacob Faibussowitsch PetscCheck(!(depth >= 0) || !(gdepth != depth), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %" PetscInt_FMT " != %" PetscInt_FMT, depth, gdepth); 13037980c9d4SMatthew G. Knepley for (d = 0; d <= gdepth; ++d) { 13047980c9d4SMatthew G. Knepley PetscBool has; 13057980c9d4SMatthew G. Knepley 13069566063dSJacob Faibussowitsch PetscCall(DMLabelHasStratum(labelNew, d, &has)); 13079566063dSJacob Faibussowitsch if (!has) PetscCall(DMLabelAddStratum(labelNew, d)); 13087980c9d4SMatthew G. Knepley } 13097980c9d4SMatthew G. Knepley } 13109566063dSJacob Faibussowitsch PetscCall(DMAddLabel(dmParallel, labelNew)); 131183e10cb3SLisandro Dalcin /* Put the output flag in the new label */ 13129566063dSJacob Faibussowitsch if (hasLabels) PetscCall(DMGetLabelOutput(dm, name, &lisOutput)); 13131c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lisOutput, &isOutput, 1, MPIU_BOOL, MPI_LAND, comm)); 13149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)labelNew, &name)); 13159566063dSJacob Faibussowitsch PetscCall(DMSetLabelOutput(dmParallel, name, isOutput)); 13169566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&labelNew)); 13170df0e737SMichael Lange } 1318695799ffSMatthew G. Knepley { 1319695799ffSMatthew G. Knepley DMLabel ctLabel; 1320695799ffSMatthew G. Knepley 1321695799ffSMatthew G. Knepley // Reset label for fast lookup 1322695799ffSMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dmParallel, &ctLabel)); 1323695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 1324695799ffSMatthew G. Knepley } 13259566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeLabels, dm, 0, 0, 0)); 13263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13270df0e737SMichael Lange } 13280df0e737SMichael Lange 1329d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeSetupTree(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel) 1330d71ae5a4SJacob Faibussowitsch { 133115078cd4SMichael Lange DM_Plex *mesh = (DM_Plex *)dm->data; 133215078cd4SMichael Lange DM_Plex *pmesh = (DM_Plex *)(dmParallel)->data; 1333a6f36705SMichael Lange MPI_Comm comm; 1334a6f36705SMichael Lange DM refTree; 1335a6f36705SMichael Lange PetscSection origParentSection, newParentSection; 1336a6f36705SMichael Lange PetscInt *origParents, *origChildIDs; 1337a6f36705SMichael Lange PetscBool flg; 1338a6f36705SMichael Lange 1339a6f36705SMichael Lange PetscFunctionBegin; 1340a6f36705SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13410c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5); 13429566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 1343a6f36705SMichael Lange 1344a6f36705SMichael Lange /* Set up tree */ 13459566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 13469566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(dmParallel, refTree)); 13479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTree(dm, &origParentSection, &origParents, &origChildIDs, NULL, NULL)); 1348a6f36705SMichael Lange if (origParentSection) { 1349a6f36705SMichael Lange PetscInt pStart, pEnd; 135008633170SToby Isaac PetscInt *newParents, *newChildIDs, *globParents; 1351a6f36705SMichael Lange PetscInt *remoteOffsetsParents, newParentSize; 1352a6f36705SMichael Lange PetscSF parentSF; 1353a6f36705SMichael Lange 13549566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmParallel, &pStart, &pEnd)); 13559566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmParallel), &newParentSection)); 13569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newParentSection, pStart, pEnd)); 13579566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(migrationSF, origParentSection, &remoteOffsetsParents, newParentSection)); 13589566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(migrationSF, origParentSection, remoteOffsetsParents, newParentSection, &parentSF)); 13599566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsParents)); 13609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newParentSection, &newParentSize)); 13619566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(newParentSize, &newParents, newParentSize, &newChildIDs)); 136208633170SToby Isaac if (original) { 136308633170SToby Isaac PetscInt numParents; 136408633170SToby Isaac 13659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(origParentSection, &numParents)); 13669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numParents, &globParents)); 13679566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(original, numParents, origParents, globParents)); 13689371c9d4SSatish Balay } else { 136908633170SToby Isaac globParents = origParents; 137008633170SToby Isaac } 13719566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(parentSF, MPIU_INT, globParents, newParents, MPI_REPLACE)); 13729566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(parentSF, MPIU_INT, globParents, newParents, MPI_REPLACE)); 13731baa6e33SBarry Smith if (original) PetscCall(PetscFree(globParents)); 13749566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(parentSF, MPIU_INT, origChildIDs, newChildIDs, MPI_REPLACE)); 13759566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(parentSF, MPIU_INT, origChildIDs, newChildIDs, MPI_REPLACE)); 13769566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newParentSize, newParents, NULL, newParents)); 137776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 13784a54e071SToby Isaac PetscInt p; 13794a54e071SToby Isaac PetscBool valid = PETSC_TRUE; 13804a54e071SToby Isaac for (p = 0; p < newParentSize; ++p) { 13819371c9d4SSatish Balay if (newParents[p] < 0) { 13829371c9d4SSatish Balay valid = PETSC_FALSE; 13839371c9d4SSatish Balay PetscCall(PetscPrintf(PETSC_COMM_SELF, "Point %" PetscInt_FMT " not in overlap SF\n", p)); 13849371c9d4SSatish Balay } 13854a54e071SToby Isaac } 138628b400f6SJacob Faibussowitsch PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map"); 13874a54e071SToby Isaac } 13889566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-parents_view", &flg)); 1389a6f36705SMichael Lange if (flg) { 13909566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Serial Parent Section: \n")); 13919566063dSJacob Faibussowitsch PetscCall(PetscSectionView(origParentSection, PETSC_VIEWER_STDOUT_(comm))); 13929566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Parallel Parent Section: \n")); 13939566063dSJacob Faibussowitsch PetscCall(PetscSectionView(newParentSection, PETSC_VIEWER_STDOUT_(comm))); 13949566063dSJacob Faibussowitsch PetscCall(PetscSFView(parentSF, NULL)); 1395a6f36705SMichael Lange } 13969566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(dmParallel, newParentSection, newParents, newChildIDs)); 13979566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newParentSection)); 13989566063dSJacob Faibussowitsch PetscCall(PetscFree2(newParents, newChildIDs)); 13999566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&parentSF)); 1400a6f36705SMichael Lange } 140115078cd4SMichael Lange pmesh->useAnchors = mesh->useAnchors; 14023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1403a6f36705SMichael Lange } 14040df0e737SMichael Lange 140598ba2d7fSLawrence Mitchell /*@ 140620f4b53cSBarry Smith DMPlexSetPartitionBalance - Should distribution of the `DM` attempt to balance the shared point partition? 140798ba2d7fSLawrence Mitchell 140898ba2d7fSLawrence Mitchell Input Parameters: 140920f4b53cSBarry Smith + dm - The `DMPLEX` object 141098ba2d7fSLawrence Mitchell - flg - Balance the partition? 141198ba2d7fSLawrence Mitchell 141298ba2d7fSLawrence Mitchell Level: intermediate 141398ba2d7fSLawrence Mitchell 141420f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetPartitionBalance()` 141598ba2d7fSLawrence Mitchell @*/ 1416d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetPartitionBalance(DM dm, PetscBool flg) 1417d71ae5a4SJacob Faibussowitsch { 141898ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 141998ba2d7fSLawrence Mitchell 142098ba2d7fSLawrence Mitchell PetscFunctionBegin; 142198ba2d7fSLawrence Mitchell mesh->partitionBalance = flg; 14223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 142398ba2d7fSLawrence Mitchell } 142498ba2d7fSLawrence Mitchell 142598ba2d7fSLawrence Mitchell /*@ 142620f4b53cSBarry Smith DMPlexGetPartitionBalance - Does distribution of the `DM` attempt to balance the shared point partition? 142798ba2d7fSLawrence Mitchell 142898ba2d7fSLawrence Mitchell Input Parameter: 142920f4b53cSBarry Smith . dm - The `DMPLEX` object 143098ba2d7fSLawrence Mitchell 143198ba2d7fSLawrence Mitchell Output Parameter: 1432a2b725a8SWilliam Gropp . flg - Balance the partition? 143398ba2d7fSLawrence Mitchell 143498ba2d7fSLawrence Mitchell Level: intermediate 143598ba2d7fSLawrence Mitchell 143620f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexSetPartitionBalance()` 143798ba2d7fSLawrence Mitchell @*/ 1438d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPartitionBalance(DM dm, PetscBool *flg) 1439d71ae5a4SJacob Faibussowitsch { 144098ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 144198ba2d7fSLawrence Mitchell 144298ba2d7fSLawrence Mitchell PetscFunctionBegin; 144398ba2d7fSLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14444f572ea9SToby Isaac PetscAssertPointer(flg, 2); 144598ba2d7fSLawrence Mitchell *flg = mesh->partitionBalance; 14463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 144798ba2d7fSLawrence Mitchell } 144898ba2d7fSLawrence Mitchell 1449fc02256fSLawrence Mitchell typedef struct { 1450fc02256fSLawrence Mitchell PetscInt vote, rank, index; 1451fc02256fSLawrence Mitchell } Petsc3Int; 1452fc02256fSLawrence Mitchell 1453fc02256fSLawrence Mitchell /* MaxLoc, but carry a third piece of information around */ 1454d71ae5a4SJacob Faibussowitsch static void MPIAPI MaxLocCarry(void *in_, void *inout_, PetscMPIInt *len_, MPI_Datatype *dtype) 1455d71ae5a4SJacob Faibussowitsch { 1456fc02256fSLawrence Mitchell Petsc3Int *a = (Petsc3Int *)inout_; 1457fc02256fSLawrence Mitchell Petsc3Int *b = (Petsc3Int *)in_; 1458fc02256fSLawrence Mitchell PetscInt i, len = *len_; 1459fc02256fSLawrence Mitchell for (i = 0; i < len; i++) { 1460fc02256fSLawrence Mitchell if (a[i].vote < b[i].vote) { 1461fc02256fSLawrence Mitchell a[i].vote = b[i].vote; 1462fc02256fSLawrence Mitchell a[i].rank = b[i].rank; 1463fc02256fSLawrence Mitchell a[i].index = b[i].index; 1464fc02256fSLawrence Mitchell } else if (a[i].vote <= b[i].vote) { 1465fc02256fSLawrence Mitchell if (a[i].rank >= b[i].rank) { 1466fc02256fSLawrence Mitchell a[i].rank = b[i].rank; 1467fc02256fSLawrence Mitchell a[i].index = b[i].index; 1468fc02256fSLawrence Mitchell } 1469fc02256fSLawrence Mitchell } 1470fc02256fSLawrence Mitchell } 1471fc02256fSLawrence Mitchell } 1472fc02256fSLawrence Mitchell 1473f5bf2dbfSMichael Lange /*@C 147420f4b53cSBarry Smith DMPlexCreatePointSF - Build a point `PetscSF` from an `PetscSF` describing a point migration 1475f5bf2dbfSMichael Lange 1476064ec1f3Sprj- Input Parameters: 147720f4b53cSBarry Smith + dm - The source `DMPLEX` object 1478f5bf2dbfSMichael Lange . migrationSF - The star forest that describes the parallel point remapping 1479d8d19677SJose E. Roman - ownership - Flag causing a vote to determine point ownership 1480f5bf2dbfSMichael Lange 1481f5bf2dbfSMichael Lange Output Parameter: 148220f4b53cSBarry Smith . pointSF - The star forest describing the point overlap in the remapped `DM` 14833618482eSVaclav Hapla 1484f5bf2dbfSMichael Lange Level: developer 1485f5bf2dbfSMichael Lange 148620f4b53cSBarry Smith Note: 148720f4b53cSBarry Smith Output `pointSF` is guaranteed to have the array of local indices (leaves) sorted. 148820f4b53cSBarry Smith 148920f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 1490f5bf2dbfSMichael Lange @*/ 1491d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointSF(DM dm, PetscSF migrationSF, PetscBool ownership, PetscSF *pointSF) 1492d71ae5a4SJacob Faibussowitsch { 149323193802SMatthew G. Knepley PetscMPIInt rank, size; 14941627f6ccSMichael Lange PetscInt p, nroots, nleaves, idx, npointLeaves; 1495f5bf2dbfSMichael Lange PetscInt *pointLocal; 1496f5bf2dbfSMichael Lange const PetscInt *leaves; 1497f5bf2dbfSMichael Lange const PetscSFNode *roots; 1498f5bf2dbfSMichael Lange PetscSFNode *rootNodes, *leafNodes, *pointRemote; 149923193802SMatthew G. Knepley Vec shifts; 1500cae3e4f3SLawrence Mitchell const PetscInt numShifts = 13759; 150123193802SMatthew G. Knepley const PetscScalar *shift = NULL; 150223193802SMatthew G. Knepley const PetscBool shiftDebug = PETSC_FALSE; 150398ba2d7fSLawrence Mitchell PetscBool balance; 1504f5bf2dbfSMichael Lange 1505f5bf2dbfSMichael Lange PetscFunctionBegin; 1506f5bf2dbfSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 15079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 15099566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreatePointSF, dm, 0, 0, 0)); 1510907a3e9cSStefano Zampini PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), pointSF)); 1511907a3e9cSStefano Zampini PetscCall(PetscSFSetFromOptions(*pointSF)); 1512907a3e9cSStefano Zampini if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 1513f5bf2dbfSMichael Lange 15149566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitionBalance(dm, &balance)); 15159566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(migrationSF, &nroots, &nleaves, &leaves, &roots)); 15169566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &rootNodes, nleaves, &leafNodes)); 1517f5bf2dbfSMichael Lange if (ownership) { 1518fc02256fSLawrence Mitchell MPI_Op op; 1519fc02256fSLawrence Mitchell MPI_Datatype datatype; 1520fc02256fSLawrence Mitchell Petsc3Int *rootVote = NULL, *leafVote = NULL; 152123193802SMatthew 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. */ 152298ba2d7fSLawrence Mitchell if (balance) { 152323193802SMatthew G. Knepley PetscRandom r; 152423193802SMatthew G. Knepley 15259566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_SELF, &r)); 15269566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(r, 0, 2467 * size)); 15279566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &shifts)); 15289566063dSJacob Faibussowitsch PetscCall(VecSetSizes(shifts, numShifts, numShifts)); 15299566063dSJacob Faibussowitsch PetscCall(VecSetType(shifts, VECSTANDARD)); 15309566063dSJacob Faibussowitsch PetscCall(VecSetRandom(shifts, r)); 15319566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&r)); 15329566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(shifts, &shift)); 153323193802SMatthew G. Knepley } 153423193802SMatthew G. Knepley 15359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nroots, &rootVote)); 15369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &leafVote)); 153723193802SMatthew G. Knepley /* Point ownership vote: Process with highest rank owns shared points */ 1538f5bf2dbfSMichael Lange for (p = 0; p < nleaves; ++p) { 153923193802SMatthew G. Knepley if (shiftDebug) { 15409371c9d4SSatish 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, 15419371c9d4SSatish Balay (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]), (rank + (shift ? (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]) : 0)) % size)); 154223193802SMatthew G. Knepley } 1543f5bf2dbfSMichael Lange /* Either put in a bid or we know we own it */ 1544fc02256fSLawrence Mitchell leafVote[p].vote = (rank + (shift ? (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]) : 0)) % size; 1545fc02256fSLawrence Mitchell leafVote[p].rank = rank; 1546fc02256fSLawrence Mitchell leafVote[p].index = p; 1547f5bf2dbfSMichael Lange } 1548f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) { 15491627f6ccSMichael Lange /* Root must not participate in the reduction, flag so that MAXLOC does not use */ 1550fc02256fSLawrence Mitchell rootVote[p].vote = -3; 1551fc02256fSLawrence Mitchell rootVote[p].rank = -3; 1552fc02256fSLawrence Mitchell rootVote[p].index = -3; 1553f5bf2dbfSMichael Lange } 15549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(3, MPIU_INT, &datatype)); 15559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&datatype)); 15569566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(&MaxLocCarry, 1, &op)); 15579566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(migrationSF, datatype, leafVote, rootVote, op)); 15589566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(migrationSF, datatype, leafVote, rootVote, op)); 15599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&op)); 15609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&datatype)); 1561c091126eSLawrence Mitchell for (p = 0; p < nroots; p++) { 1562fc02256fSLawrence Mitchell rootNodes[p].rank = rootVote[p].rank; 1563fc02256fSLawrence Mitchell rootNodes[p].index = rootVote[p].index; 1564c091126eSLawrence Mitchell } 15659566063dSJacob Faibussowitsch PetscCall(PetscFree(leafVote)); 15669566063dSJacob Faibussowitsch PetscCall(PetscFree(rootVote)); 1567f5bf2dbfSMichael Lange } else { 1568f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) { 1569f5bf2dbfSMichael Lange rootNodes[p].index = -1; 1570f5bf2dbfSMichael Lange rootNodes[p].rank = rank; 1571fc02256fSLawrence Mitchell } 1572f5bf2dbfSMichael Lange for (p = 0; p < nleaves; p++) { 1573f5bf2dbfSMichael Lange /* Write new local id into old location */ 1574ad540459SPierre Jolivet if (roots[p].rank == rank) rootNodes[roots[p].index].index = leaves ? leaves[p] : p; 1575f5bf2dbfSMichael Lange } 1576f5bf2dbfSMichael Lange } 15779566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(migrationSF, MPIU_2INT, rootNodes, leafNodes, MPI_REPLACE)); 15789566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(migrationSF, MPIU_2INT, rootNodes, leafNodes, MPI_REPLACE)); 1579f5bf2dbfSMichael Lange 158023193802SMatthew G. Knepley for (npointLeaves = 0, p = 0; p < nleaves; p++) { 1581b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) npointLeaves++; 158223193802SMatthew G. Knepley } 15839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npointLeaves, &pointLocal)); 15849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npointLeaves, &pointRemote)); 1585f5bf2dbfSMichael Lange for (idx = 0, p = 0; p < nleaves; p++) { 1586b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) { 15873618482eSVaclav Hapla /* Note that pointLocal is automatically sorted as it is sublist of 0, ..., nleaves-1 */ 1588f5bf2dbfSMichael Lange pointLocal[idx] = p; 1589f5bf2dbfSMichael Lange pointRemote[idx] = leafNodes[p]; 1590f5bf2dbfSMichael Lange idx++; 1591f5bf2dbfSMichael Lange } 1592f5bf2dbfSMichael Lange } 159323193802SMatthew G. Knepley if (shift) { 15949566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(shifts, &shift)); 15959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shifts)); 159623193802SMatthew G. Knepley } 15979566063dSJacob Faibussowitsch if (shiftDebug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), PETSC_STDOUT)); 15989566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*pointSF, nleaves, npointLeaves, pointLocal, PETSC_OWN_POINTER, pointRemote, PETSC_OWN_POINTER)); 15999566063dSJacob Faibussowitsch PetscCall(PetscFree2(rootNodes, leafNodes)); 16009566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreatePointSF, dm, 0, 0, 0)); 1601d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, *pointSF, PETSC_FALSE)); 16023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1603f5bf2dbfSMichael Lange } 1604f5bf2dbfSMichael Lange 160515078cd4SMichael Lange /*@C 160620f4b53cSBarry Smith DMPlexMigrate - Migrates internal `DM` data over the supplied star forest 160715078cd4SMichael Lange 160820f4b53cSBarry Smith Collective 160983655b49SVáclav Hapla 1610064ec1f3Sprj- Input Parameters: 161120f4b53cSBarry Smith + dm - The source `DMPLEX` object 1612d8d19677SJose E. Roman - sf - The star forest communication context describing the migration pattern 161315078cd4SMichael Lange 161415078cd4SMichael Lange Output Parameter: 161520f4b53cSBarry Smith . targetDM - The target `DMPLEX` object 161615078cd4SMichael Lange 1617b9f40539SMichael Lange Level: intermediate 161815078cd4SMichael Lange 161920f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 162015078cd4SMichael Lange @*/ 1621d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMigrate(DM dm, PetscSF sf, DM targetDM) 1622d71ae5a4SJacob Faibussowitsch { 1623b9f40539SMichael Lange MPI_Comm comm; 1624cc1750acSStefano Zampini PetscInt dim, cdim, nroots; 1625b9f40539SMichael Lange PetscSF sfPoint; 162615078cd4SMichael Lange ISLocalToGlobalMapping ltogMigration; 1627ac04eaf7SToby Isaac ISLocalToGlobalMapping ltogOriginal = NULL; 162815078cd4SMichael Lange 162915078cd4SMichael Lange PetscFunctionBegin; 163015078cd4SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 16319566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Migrate, dm, 0, 0, 0)); 16329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 16339566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 16349566063dSJacob Faibussowitsch PetscCall(DMSetDimension(targetDM, dim)); 16359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 16369566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(targetDM, cdim)); 163715078cd4SMichael Lange 1638bfb0467fSMichael Lange /* Check for a one-to-all distribution pattern */ 16399566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 16409566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 1641bfb0467fSMichael Lange if (nroots >= 0) { 1642b9f40539SMichael Lange IS isOriginal; 1643ac04eaf7SToby Isaac PetscInt n, size, nleaves; 1644ac04eaf7SToby Isaac PetscInt *numbering_orig, *numbering_new; 1645367003a6SStefano Zampini 1646b9f40539SMichael Lange /* Get the original point numbering */ 16479566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &isOriginal)); 16489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(isOriginal, <ogOriginal)); 16499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(ltogOriginal, &size)); 16509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltogOriginal, (const PetscInt **)&numbering_orig)); 1651b9f40539SMichael Lange /* Convert to positive global numbers */ 16529371c9d4SSatish Balay for (n = 0; n < size; n++) { 16539371c9d4SSatish Balay if (numbering_orig[n] < 0) numbering_orig[n] = -(numbering_orig[n] + 1); 16549371c9d4SSatish Balay } 1655b9f40539SMichael Lange /* Derive the new local-to-global mapping from the old one */ 16569566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, NULL, NULL)); 16579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &numbering_new)); 16589566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, numbering_orig, numbering_new, MPI_REPLACE)); 16599566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, numbering_orig, numbering_new, MPI_REPLACE)); 16609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, nleaves, numbering_new, PETSC_OWN_POINTER, <ogMigration)); 16619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogOriginal, (const PetscInt **)&numbering_orig)); 16629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isOriginal)); 166315078cd4SMichael Lange } else { 1664bfb0467fSMichael Lange /* One-to-all distribution pattern: We can derive LToG from SF */ 16659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateSF(sf, 0, <ogMigration)); 166615078cd4SMichael Lange } 1667a5a902f7SVaclav Hapla PetscCall(PetscObjectSetName((PetscObject)ltogMigration, "Point renumbering for DM migration")); 1668a5a902f7SVaclav Hapla PetscCall(ISLocalToGlobalMappingViewFromOptions(ltogMigration, (PetscObject)dm, "-partition_view")); 166915078cd4SMichael Lange /* Migrate DM data to target DM */ 16709566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeCones(dm, sf, ltogOriginal, ltogMigration, targetDM)); 16719566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeLabels(dm, sf, targetDM)); 16729566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeCoordinates(dm, sf, targetDM)); 16739566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetupTree(dm, sf, ltogOriginal, ltogMigration, targetDM)); 16749566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<ogOriginal)); 16759566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<ogMigration)); 16769566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Migrate, dm, 0, 0, 0)); 16773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 167815078cd4SMichael Lange } 167915078cd4SMichael Lange 168000a1aa47SMatthew G. Knepley /*@ 168100a1aa47SMatthew G. Knepley DMPlexRemapMigrationSF - Rewrite the distribution SF to account for overlap 168200a1aa47SMatthew G. Knepley 168300a1aa47SMatthew G. Knepley Collective 168400a1aa47SMatthew G. Knepley 168500a1aa47SMatthew G. Knepley Input Parameters: 168600a1aa47SMatthew G. Knepley + sfOverlap - The `PetscSF` object just for the overlap 168700a1aa47SMatthew G. Knepley - sfMigration - The original distribution `PetscSF` object 168800a1aa47SMatthew G. Knepley 168900a1aa47SMatthew G. Knepley Output Parameters: 169000a1aa47SMatthew G. Knepley . sfMigrationNew - A rewritten `PetscSF` object that incorporates the overlap 169100a1aa47SMatthew G. Knepley 169200a1aa47SMatthew G. Knepley Level: developer 169300a1aa47SMatthew G. Knepley 169400a1aa47SMatthew G. Knepley .seealso: `DMPLEX`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()`, `DMPlexGetOverlap()` 169500a1aa47SMatthew G. Knepley @*/ 169600a1aa47SMatthew G. Knepley PetscErrorCode DMPlexRemapMigrationSF(PetscSF sfOverlap, PetscSF sfMigration, PetscSF *sfMigrationNew) 169700a1aa47SMatthew G. Knepley { 169800a1aa47SMatthew G. Knepley PetscSFNode *newRemote, *permRemote; 169900a1aa47SMatthew G. Knepley const PetscInt *oldLeaves; 170000a1aa47SMatthew G. Knepley const PetscSFNode *oldRemote; 170100a1aa47SMatthew G. Knepley PetscInt nroots, nleaves, noldleaves; 170200a1aa47SMatthew G. Knepley 170300a1aa47SMatthew G. Knepley PetscFunctionBegin; 170400a1aa47SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfMigration, &nroots, &noldleaves, &oldLeaves, &oldRemote)); 170500a1aa47SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfOverlap, NULL, &nleaves, NULL, NULL)); 170600a1aa47SMatthew G. Knepley PetscCall(PetscMalloc1(nleaves, &newRemote)); 170700a1aa47SMatthew G. Knepley /* oldRemote: original root point mapping to original leaf point 170800a1aa47SMatthew G. Knepley newRemote: original leaf point mapping to overlapped leaf point */ 170900a1aa47SMatthew G. Knepley if (oldLeaves) { 171000a1aa47SMatthew G. Knepley /* After stratification, the migration remotes may not be in root (canonical) order, so we reorder using the leaf numbering */ 171100a1aa47SMatthew G. Knepley PetscCall(PetscMalloc1(noldleaves, &permRemote)); 171200a1aa47SMatthew G. Knepley for (PetscInt l = 0; l < noldleaves; ++l) permRemote[oldLeaves[l]] = oldRemote[l]; 171300a1aa47SMatthew G. Knepley oldRemote = permRemote; 171400a1aa47SMatthew G. Knepley } 171500a1aa47SMatthew G. Knepley PetscCall(PetscSFBcastBegin(sfOverlap, MPIU_2INT, oldRemote, newRemote, MPI_REPLACE)); 171600a1aa47SMatthew G. Knepley PetscCall(PetscSFBcastEnd(sfOverlap, MPIU_2INT, oldRemote, newRemote, MPI_REPLACE)); 171700a1aa47SMatthew G. Knepley if (oldLeaves) PetscCall(PetscFree(oldRemote)); 171800a1aa47SMatthew G. Knepley PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)sfOverlap), sfMigrationNew)); 171900a1aa47SMatthew G. Knepley PetscCall(PetscSFSetGraph(*sfMigrationNew, nroots, nleaves, NULL, PETSC_OWN_POINTER, newRemote, PETSC_OWN_POINTER)); 172000a1aa47SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 172100a1aa47SMatthew G. Knepley } 172200a1aa47SMatthew G. Knepley 17233b8f15a2SMatthew G. Knepley /*@C 172470034214SMatthew G. Knepley DMPlexDistribute - Distributes the mesh and any associated sections. 172570034214SMatthew G. Knepley 172620f4b53cSBarry Smith Collective 172770034214SMatthew G. Knepley 1728064ec1f3Sprj- Input Parameters: 172920f4b53cSBarry Smith + dm - The original `DMPLEX` object 173070034214SMatthew G. Knepley - overlap - The overlap of partitions, 0 is the default 173170034214SMatthew G. Knepley 1732064ec1f3Sprj- Output Parameters: 173320f4b53cSBarry Smith + sf - The `PetscSF` used for point distribution, or `NULL` if not needed 173420f4b53cSBarry Smith - dmParallel - The distributed `DMPLEX` object 173570034214SMatthew G. Knepley 173670034214SMatthew G. Knepley Level: intermediate 173770034214SMatthew G. Knepley 173820f4b53cSBarry Smith Note: 173920f4b53cSBarry Smith If the mesh was not distributed, the output `dmParallel` will be `NULL`. 174020f4b53cSBarry Smith 174120f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function 174220f4b53cSBarry Smith representation on the mesh. 174320f4b53cSBarry Smith 174420f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexGetOverlap()` 174570034214SMatthew G. Knepley @*/ 1746d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistribute(DM dm, PetscInt overlap, PetscSF *sf, DM *dmParallel) 1747d71ae5a4SJacob Faibussowitsch { 174870034214SMatthew G. Knepley MPI_Comm comm; 174915078cd4SMichael Lange PetscPartitioner partitioner; 1750f8987ae8SMichael Lange IS cellPart; 1751f8987ae8SMichael Lange PetscSection cellPartSection; 1752cf86098cSMatthew G. Knepley DM dmCoord; 1753f8987ae8SMichael Lange DMLabel lblPartition, lblMigration; 1754874ddda9SLisandro Dalcin PetscSF sfMigration, sfStratified, sfPoint; 175598ba2d7fSLawrence Mitchell PetscBool flg, balance; 1756874ddda9SLisandro Dalcin PetscMPIInt rank, size; 175770034214SMatthew G. Knepley 175870034214SMatthew G. Knepley PetscFunctionBegin; 175970034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1760d5c515a1SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 2); 17614f572ea9SToby Isaac if (sf) PetscAssertPointer(sf, 3); 17624f572ea9SToby Isaac PetscAssertPointer(dmParallel, 4); 176370034214SMatthew G. Knepley 17640c86c063SLisandro Dalcin if (sf) *sf = NULL; 17650c86c063SLisandro Dalcin *dmParallel = NULL; 17669566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 17679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 17689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 17693ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 177070034214SMatthew G. Knepley 17719566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Distribute, dm, 0, 0, 0)); 177215078cd4SMichael Lange /* Create cell partition */ 17739566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0)); 17749566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &cellPartSection)); 17759566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &partitioner)); 17769566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDMPlexPartition(partitioner, dm, NULL, cellPartSection, &cellPart)); 17779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartSelf, dm, 0, 0, 0)); 1778f8987ae8SMichael Lange { 1779f8987ae8SMichael Lange /* Convert partition to DMLabel */ 1780825f8a23SLisandro Dalcin IS is; 1781825f8a23SLisandro Dalcin PetscHSetI ht; 1782f8987ae8SMichael Lange const PetscInt *points; 17838e330a33SStefano Zampini PetscInt *iranks; 17848e330a33SStefano Zampini PetscInt pStart, pEnd, proc, npoints, poff = 0, nranks; 1785825f8a23SLisandro Dalcin 17869566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point Partition", &lblPartition)); 1787825f8a23SLisandro Dalcin /* Preallocate strata */ 17889566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 17899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1790825f8a23SLisandro Dalcin for (proc = pStart; proc < pEnd; proc++) { 17919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints)); 17929566063dSJacob Faibussowitsch if (npoints) PetscCall(PetscHSetIAdd(ht, proc)); 1793825f8a23SLisandro Dalcin } 17949566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ht, &nranks)); 17959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nranks, &iranks)); 17969566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ht, &poff, iranks)); 17979566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 17989566063dSJacob Faibussowitsch PetscCall(DMLabelAddStrata(lblPartition, nranks, iranks)); 17999566063dSJacob Faibussowitsch PetscCall(PetscFree(iranks)); 1800825f8a23SLisandro Dalcin /* Inline DMPlexPartitionLabelClosure() */ 18019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellPart, &points)); 18029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1803f8987ae8SMichael Lange for (proc = pStart; proc < pEnd; proc++) { 18049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints)); 1805825f8a23SLisandro Dalcin if (!npoints) continue; 18069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellPartSection, proc, &poff)); 18079566063dSJacob Faibussowitsch PetscCall(DMPlexClosurePoints_Private(dm, npoints, points + poff, &is)); 18089566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(lblPartition, proc, is)); 18099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1810f8987ae8SMichael Lange } 18119566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellPart, &points)); 1812f8987ae8SMichael Lange } 18139566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartSelf, dm, 0, 0, 0)); 18146e203dd9SStefano Zampini 18159566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point migration", &lblMigration)); 18169566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelInvert(dm, lblPartition, NULL, lblMigration)); 18173ac0285dSStefano Zampini PetscCall(DMPlexPartitionLabelCreateSF(dm, lblMigration, PETSC_TRUE, &sfMigration)); 18189566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, sfMigration, &sfStratified)); 18199566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration)); 182043f7d02bSMichael Lange sfMigration = sfStratified; 18219566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sfMigration)); 18229566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0)); 18239566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-partition_view", &flg)); 182470034214SMatthew G. Knepley if (flg) { 18259566063dSJacob Faibussowitsch PetscCall(DMLabelView(lblPartition, PETSC_VIEWER_STDOUT_(comm))); 18269566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfMigration, PETSC_VIEWER_STDOUT_(comm))); 182770034214SMatthew G. Knepley } 1828f8987ae8SMichael Lange 182915078cd4SMichael Lange /* Create non-overlapping parallel DM and migrate internal data */ 18309566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, dmParallel)); 18319566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*dmParallel, "Parallel Mesh")); 18329566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(dm, sfMigration, *dmParallel)); 183370034214SMatthew G. Knepley 1834a157612eSMichael Lange /* Build the point SF without overlap */ 18359566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitionBalance(dm, &balance)); 18369566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitionBalance(*dmParallel, balance)); 18379566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*dmParallel, sfMigration, PETSC_TRUE, &sfPoint)); 18389566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*dmParallel, sfPoint)); 18395f06a3ddSJed Brown PetscCall(DMPlexMigrateIsoperiodicFaceSF_Internal(dm, *dmParallel, sfMigration)); 18409566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dmParallel, &dmCoord)); 18419566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 18429566063dSJacob Faibussowitsch if (flg) PetscCall(PetscSFView(sfPoint, NULL)); 184370034214SMatthew G. Knepley 1844a157612eSMichael Lange if (overlap > 0) { 184515078cd4SMichael Lange DM dmOverlap; 184615078cd4SMichael Lange PetscSF sfOverlap, sfOverlapPoint; 1847524e35f8SStefano Zampini 1848a157612eSMichael Lange /* Add the partition overlap to the distributed DM */ 18499566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeOverlap(*dmParallel, overlap, &sfOverlap, &dmOverlap)); 18509566063dSJacob Faibussowitsch PetscCall(DMDestroy(dmParallel)); 1851a157612eSMichael Lange *dmParallel = dmOverlap; 1852c389ea9fSToby Isaac if (flg) { 18539566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Overlap Migration SF:\n")); 18549566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfOverlap, NULL)); 1855c389ea9fSToby Isaac } 185643331d4aSMichael Lange 1857f8987ae8SMichael Lange /* Re-map the migration SF to establish the full migration pattern */ 185800a1aa47SMatthew G. Knepley PetscCall(DMPlexRemapMigrationSF(sfOverlap, sfMigration, &sfOverlapPoint)); 18599566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfOverlap)); 18609566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration)); 186115078cd4SMichael Lange sfMigration = sfOverlapPoint; 1862c389ea9fSToby Isaac } 1863bf5244c7SMatthew G. Knepley /* Cleanup Partition */ 18649566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblPartition)); 18659566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblMigration)); 18669566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cellPartSection)); 18679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellPart)); 186812a88998SMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *dmParallel)); 186912a88998SMatthew G. Knepley // Create sfNatural, need discretization information 18709566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *dmParallel)); 187166fe0bfeSMatthew G. Knepley if (dm->useNatural) { 187266fe0bfeSMatthew G. Knepley PetscSection section; 187366fe0bfeSMatthew G. Knepley 1874fc6a3818SBlaise Bourdin PetscCall(DMSetUseNatural(*dmParallel, PETSC_TRUE)); 1875fc6a3818SBlaise Bourdin PetscCall(DMGetLocalSection(dm, §ion)); 1876fc6a3818SBlaise Bourdin 18778aee0f92SAlexis Marboeuf /* First DM with useNatural = PETSC_TRUE is considered natural */ 18788aee0f92SAlexis Marboeuf /* sfMigration and sfNatural are respectively the point and dofs SFs mapping to this natural DM */ 1879fc6a3818SBlaise Bourdin /* Compose with a previous sfNatural if present */ 1880fc6a3818SBlaise Bourdin if (dm->sfNatural) { 1881fc6a3818SBlaise Bourdin PetscSF natSF; 1882fc6a3818SBlaise Bourdin 1883fc6a3818SBlaise Bourdin PetscCall(DMPlexCreateGlobalToNaturalSF(*dmParallel, section, sfMigration, &natSF)); 1884fc6a3818SBlaise Bourdin PetscCall(PetscSFCompose(dm->sfNatural, natSF, &(*dmParallel)->sfNatural)); 1885fc6a3818SBlaise Bourdin PetscCall(PetscSFDestroy(&natSF)); 1886fc6a3818SBlaise Bourdin } else { 1887fc6a3818SBlaise Bourdin PetscCall(DMPlexCreateGlobalToNaturalSF(*dmParallel, section, sfMigration, &(*dmParallel)->sfNatural)); 1888fc6a3818SBlaise Bourdin } 18898aee0f92SAlexis Marboeuf /* Compose with a previous sfMigration if present */ 18908aee0f92SAlexis Marboeuf if (dm->sfMigration) { 18918aee0f92SAlexis Marboeuf PetscSF naturalPointSF; 18928aee0f92SAlexis Marboeuf 18938aee0f92SAlexis Marboeuf PetscCall(PetscSFCompose(dm->sfMigration, sfMigration, &naturalPointSF)); 18948aee0f92SAlexis Marboeuf PetscCall(PetscSFDestroy(&sfMigration)); 18958aee0f92SAlexis Marboeuf sfMigration = naturalPointSF; 18968aee0f92SAlexis Marboeuf } 189766fe0bfeSMatthew G. Knepley } 1898721cbd76SMatthew G. Knepley /* Cleanup */ 18999371c9d4SSatish Balay if (sf) { 19009371c9d4SSatish Balay *sf = sfMigration; 19019371c9d4SSatish Balay } else PetscCall(PetscSFDestroy(&sfMigration)); 19029566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 19039566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Distribute, dm, 0, 0, 0)); 19043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 190570034214SMatthew G. Knepley } 1906a157612eSMichael Lange 1907907a3e9cSStefano Zampini PetscErrorCode DMPlexDistributeOverlap_Internal(DM dm, PetscInt overlap, MPI_Comm newcomm, const char *ovlboundary, PetscSF *sf, DM *dmOverlap) 1908907a3e9cSStefano Zampini { 1909907a3e9cSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 1910907a3e9cSStefano Zampini MPI_Comm comm; 1911907a3e9cSStefano Zampini PetscMPIInt size, rank; 1912907a3e9cSStefano Zampini PetscSection rootSection, leafSection; 1913907a3e9cSStefano Zampini IS rootrank, leafrank; 1914907a3e9cSStefano Zampini DM dmCoord; 1915907a3e9cSStefano Zampini DMLabel lblOverlap; 1916907a3e9cSStefano Zampini PetscSF sfOverlap, sfStratified, sfPoint; 1917907a3e9cSStefano Zampini PetscBool clear_ovlboundary; 1918907a3e9cSStefano Zampini 1919907a3e9cSStefano Zampini PetscFunctionBegin; 1920907a3e9cSStefano Zampini if (sf) *sf = NULL; 1921907a3e9cSStefano Zampini *dmOverlap = NULL; 1922907a3e9cSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 1923907a3e9cSStefano Zampini PetscCallMPI(MPI_Comm_size(comm, &size)); 1924907a3e9cSStefano Zampini PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1925907a3e9cSStefano Zampini if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 1926907a3e9cSStefano Zampini { 1927907a3e9cSStefano Zampini // We need to get options for the _already_distributed mesh, so it must be done here 1928907a3e9cSStefano Zampini PetscInt overlap; 1929907a3e9cSStefano Zampini const char *prefix; 1930907a3e9cSStefano Zampini char oldPrefix[PETSC_MAX_PATH_LEN]; 1931907a3e9cSStefano Zampini 1932907a3e9cSStefano Zampini oldPrefix[0] = '\0'; 1933907a3e9cSStefano Zampini PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 1934907a3e9cSStefano Zampini PetscCall(PetscStrncpy(oldPrefix, prefix, sizeof(oldPrefix))); 1935907a3e9cSStefano Zampini PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, "dist_")); 1936907a3e9cSStefano Zampini PetscCall(DMPlexGetOverlap(dm, &overlap)); 1937907a3e9cSStefano Zampini PetscObjectOptionsBegin((PetscObject)dm); 1938907a3e9cSStefano Zampini PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 1939907a3e9cSStefano Zampini PetscOptionsEnd(); 1940907a3e9cSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix[0] == '\0' ? NULL : oldPrefix)); 1941907a3e9cSStefano Zampini } 1942907a3e9cSStefano Zampini if (ovlboundary) { 1943907a3e9cSStefano Zampini PetscBool flg; 1944907a3e9cSStefano Zampini PetscCall(DMHasLabel(dm, ovlboundary, &flg)); 1945907a3e9cSStefano Zampini if (!flg) { 1946907a3e9cSStefano Zampini DMLabel label; 1947907a3e9cSStefano Zampini 1948907a3e9cSStefano Zampini PetscCall(DMCreateLabel(dm, ovlboundary)); 1949907a3e9cSStefano Zampini PetscCall(DMGetLabel(dm, ovlboundary, &label)); 1950907a3e9cSStefano Zampini PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label)); 1951907a3e9cSStefano Zampini clear_ovlboundary = PETSC_TRUE; 1952907a3e9cSStefano Zampini } 1953907a3e9cSStefano Zampini } 1954907a3e9cSStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 1955907a3e9cSStefano Zampini /* Compute point overlap with neighbouring processes on the distributed DM */ 1956907a3e9cSStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0)); 1957907a3e9cSStefano Zampini PetscCall(PetscSectionCreate(newcomm, &rootSection)); 1958907a3e9cSStefano Zampini PetscCall(PetscSectionCreate(newcomm, &leafSection)); 1959907a3e9cSStefano Zampini PetscCall(DMPlexDistributeOwnership(dm, rootSection, &rootrank, leafSection, &leafrank)); 1960907a3e9cSStefano Zampini if (mesh->numOvLabels) PetscCall(DMPlexCreateOverlapLabelFromLabels(dm, mesh->numOvLabels, mesh->ovLabels, mesh->ovValues, mesh->numOvExLabels, mesh->ovExLabels, mesh->ovExValues, rootSection, rootrank, leafSection, leafrank, &lblOverlap)); 1961907a3e9cSStefano Zampini else PetscCall(DMPlexCreateOverlapLabel(dm, overlap, rootSection, rootrank, leafSection, leafrank, &lblOverlap)); 1962907a3e9cSStefano Zampini /* Convert overlap label to stratified migration SF */ 19633ac0285dSStefano Zampini PetscCall(DMPlexPartitionLabelCreateSF(dm, lblOverlap, PETSC_FALSE, &sfOverlap)); 1964907a3e9cSStefano Zampini PetscCall(DMPlexStratifyMigrationSF(dm, sfOverlap, &sfStratified)); 1965907a3e9cSStefano Zampini PetscCall(PetscSFDestroy(&sfOverlap)); 1966907a3e9cSStefano Zampini sfOverlap = sfStratified; 1967907a3e9cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)sfOverlap, "Overlap SF")); 1968907a3e9cSStefano Zampini PetscCall(PetscSFSetFromOptions(sfOverlap)); 1969907a3e9cSStefano Zampini 1970907a3e9cSStefano Zampini PetscCall(PetscSectionDestroy(&rootSection)); 1971907a3e9cSStefano Zampini PetscCall(PetscSectionDestroy(&leafSection)); 1972907a3e9cSStefano Zampini PetscCall(ISDestroy(&rootrank)); 1973907a3e9cSStefano Zampini PetscCall(ISDestroy(&leafrank)); 1974907a3e9cSStefano Zampini PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0)); 1975907a3e9cSStefano Zampini 1976907a3e9cSStefano Zampini /* Build the overlapping DM */ 1977907a3e9cSStefano Zampini PetscCall(DMPlexCreate(newcomm, dmOverlap)); 1978907a3e9cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*dmOverlap, "Parallel Mesh")); 1979907a3e9cSStefano Zampini PetscCall(DMPlexMigrate(dm, sfOverlap, *dmOverlap)); 1980907a3e9cSStefano Zampini /* Store the overlap in the new DM */ 1981907a3e9cSStefano Zampini PetscCall(DMPlexSetOverlap_Plex(*dmOverlap, dm, overlap)); 1982907a3e9cSStefano Zampini /* Build the new point SF */ 1983907a3e9cSStefano Zampini PetscCall(DMPlexCreatePointSF(*dmOverlap, sfOverlap, PETSC_FALSE, &sfPoint)); 1984907a3e9cSStefano Zampini PetscCall(DMSetPointSF(*dmOverlap, sfPoint)); 1985907a3e9cSStefano Zampini PetscCall(DMGetCoordinateDM(*dmOverlap, &dmCoord)); 1986907a3e9cSStefano Zampini if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 1987907a3e9cSStefano Zampini PetscCall(DMGetCellCoordinateDM(*dmOverlap, &dmCoord)); 1988907a3e9cSStefano Zampini if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 1989907a3e9cSStefano Zampini PetscCall(PetscSFDestroy(&sfPoint)); 1990907a3e9cSStefano Zampini PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *dmOverlap)); 1991907a3e9cSStefano Zampini /* TODO: labels stored inside the DS for regions should be handled here */ 1992907a3e9cSStefano Zampini PetscCall(DMCopyDisc(dm, *dmOverlap)); 1993907a3e9cSStefano Zampini /* Cleanup overlap partition */ 1994907a3e9cSStefano Zampini PetscCall(DMLabelDestroy(&lblOverlap)); 1995907a3e9cSStefano Zampini if (sf) *sf = sfOverlap; 1996907a3e9cSStefano Zampini else PetscCall(PetscSFDestroy(&sfOverlap)); 1997907a3e9cSStefano Zampini if (ovlboundary) { 1998907a3e9cSStefano Zampini DMLabel label; 1999907a3e9cSStefano Zampini PetscBool flg; 2000907a3e9cSStefano Zampini 2001907a3e9cSStefano Zampini if (clear_ovlboundary) PetscCall(DMRemoveLabel(dm, ovlboundary, NULL)); 2002907a3e9cSStefano Zampini PetscCall(DMHasLabel(*dmOverlap, ovlboundary, &flg)); 200300045ab3SPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing %s label", ovlboundary); 2004907a3e9cSStefano Zampini PetscCall(DMGetLabel(*dmOverlap, ovlboundary, &label)); 2005907a3e9cSStefano Zampini PetscCall(DMPlexMarkBoundaryFaces_Internal(*dmOverlap, 1, 0, label, PETSC_TRUE)); 2006907a3e9cSStefano Zampini } 2007907a3e9cSStefano Zampini PetscCall(PetscLogEventEnd(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 2008907a3e9cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2009907a3e9cSStefano Zampini } 2010907a3e9cSStefano Zampini 2011a157612eSMichael Lange /*@C 201220f4b53cSBarry Smith DMPlexDistributeOverlap - Add partition overlap to a distributed non-overlapping `DM`. 2013a157612eSMichael Lange 201420f4b53cSBarry Smith Collective 2015a157612eSMichael Lange 2016064ec1f3Sprj- Input Parameters: 201720f4b53cSBarry Smith + dm - The non-overlapping distributed `DMPLEX` object 201857fe9a49SVaclav Hapla - overlap - The overlap of partitions (the same on all ranks) 2019a157612eSMichael Lange 2020064ec1f3Sprj- Output Parameters: 2021*f13dfd9eSBarry Smith + sf - The `PetscSF` used for point distribution, or pass `NULL` if not needed 2022*f13dfd9eSBarry Smith - dmOverlap - The overlapping distributed `DMPLEX` object 2023a157612eSMichael Lange 2024c506a872SMatthew G. Knepley Options Database Keys: 2025c506a872SMatthew G. Knepley + -dm_plex_overlap_labels <name1,name2,...> - List of overlap label names 2026c506a872SMatthew G. Knepley . -dm_plex_overlap_values <int1,int2,...> - List of overlap label values 2027c506a872SMatthew G. Knepley . -dm_plex_overlap_exclude_label <name> - Label used to exclude points from overlap 2028c506a872SMatthew G. Knepley - -dm_plex_overlap_exclude_value <int> - Label value used to exclude points from overlap 2029c506a872SMatthew G. Knepley 2030dccdeccaSVaclav Hapla Level: advanced 2031a157612eSMichael Lange 203220f4b53cSBarry Smith Notes: 203320f4b53cSBarry Smith If the mesh was not distributed, the return value is `NULL`. 203420f4b53cSBarry Smith 203520f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function 203620f4b53cSBarry Smith representation on the mesh. 203720f4b53cSBarry Smith 203820f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMPlexCreateOverlapLabel()`, `DMPlexGetOverlap()` 2039a157612eSMichael Lange @*/ 2040d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeOverlap(DM dm, PetscInt overlap, PetscSF *sf, DM *dmOverlap) 2041d71ae5a4SJacob Faibussowitsch { 2042a157612eSMichael Lange PetscFunctionBegin; 2043a157612eSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 204457fe9a49SVaclav Hapla PetscValidLogicalCollectiveInt(dm, overlap, 2); 20454f572ea9SToby Isaac if (sf) PetscAssertPointer(sf, 3); 20464f572ea9SToby Isaac PetscAssertPointer(dmOverlap, 4); 2047907a3e9cSStefano Zampini PetscCall(DMPlexDistributeOverlap_Internal(dm, overlap, PetscObjectComm((PetscObject)dm), NULL, sf, dmOverlap)); 20483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2049a157612eSMichael Lange } 20506462276dSToby Isaac 2051d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap_Plex(DM dm, PetscInt *overlap) 2052d71ae5a4SJacob Faibussowitsch { 2053cb54e036SVaclav Hapla DM_Plex *mesh = (DM_Plex *)dm->data; 2054cb54e036SVaclav Hapla 2055cb54e036SVaclav Hapla PetscFunctionBegin; 2056cb54e036SVaclav Hapla *overlap = mesh->overlap; 20573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2058cb54e036SVaclav Hapla } 2059cb54e036SVaclav Hapla 2060d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap_Plex(DM dm, DM dmSrc, PetscInt overlap) 2061d71ae5a4SJacob Faibussowitsch { 206260667520SVaclav Hapla DM_Plex *mesh = NULL; 206360667520SVaclav Hapla DM_Plex *meshSrc = NULL; 206460667520SVaclav Hapla 206560667520SVaclav Hapla PetscFunctionBegin; 206660667520SVaclav Hapla PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 206760667520SVaclav Hapla mesh = (DM_Plex *)dm->data; 206860667520SVaclav Hapla if (dmSrc) { 206960667520SVaclav Hapla PetscValidHeaderSpecificType(dmSrc, DM_CLASSID, 2, DMPLEX); 207060667520SVaclav Hapla meshSrc = (DM_Plex *)dmSrc->data; 20719ed9361bSToby Isaac mesh->overlap = meshSrc->overlap; 20729ed9361bSToby Isaac } else { 20739ed9361bSToby Isaac mesh->overlap = 0; 207460667520SVaclav Hapla } 20759ed9361bSToby Isaac mesh->overlap += overlap; 20763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 207760667520SVaclav Hapla } 207860667520SVaclav Hapla 2079cb54e036SVaclav Hapla /*@ 2080c506a872SMatthew G. Knepley DMPlexGetOverlap - Get the width of the cell overlap 2081cb54e036SVaclav Hapla 208220f4b53cSBarry Smith Not Collective 2083cb54e036SVaclav Hapla 2084cb54e036SVaclav Hapla Input Parameter: 208520f4b53cSBarry Smith . dm - The `DM` 2086cb54e036SVaclav Hapla 2087064ec1f3Sprj- Output Parameter: 2088c506a872SMatthew G. Knepley . overlap - the width of the cell overlap 2089cb54e036SVaclav Hapla 2090cb54e036SVaclav Hapla Level: intermediate 2091cb54e036SVaclav Hapla 209220f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexSetOverlap()`, `DMPlexDistribute()` 2093cb54e036SVaclav Hapla @*/ 2094d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap(DM dm, PetscInt *overlap) 2095d71ae5a4SJacob Faibussowitsch { 2096cb54e036SVaclav Hapla PetscFunctionBegin; 2097cb54e036SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20984f572ea9SToby Isaac PetscAssertPointer(overlap, 2); 2099cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexGetOverlap_C", (DM, PetscInt *), (dm, overlap)); 21003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2101cb54e036SVaclav Hapla } 2102cb54e036SVaclav Hapla 2103c506a872SMatthew G. Knepley /*@ 2104c506a872SMatthew G. Knepley DMPlexSetOverlap - Set the width of the cell overlap 2105c506a872SMatthew G. Knepley 210620f4b53cSBarry Smith Logically Collective 2107c506a872SMatthew G. Knepley 2108c506a872SMatthew G. Knepley Input Parameters: 210920f4b53cSBarry Smith + dm - The `DM` 211020f4b53cSBarry Smith . dmSrc - The `DM` that produced this one, or `NULL` 2111c506a872SMatthew G. Knepley - overlap - the width of the cell overlap 2112c506a872SMatthew G. Knepley 2113c506a872SMatthew G. Knepley Level: intermediate 2114c506a872SMatthew G. Knepley 211520f4b53cSBarry Smith Note: 211620f4b53cSBarry Smith The overlap from `dmSrc` is added to `dm` 211720f4b53cSBarry Smith 211820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexGetOverlap()`, `DMPlexDistribute()` 2119c506a872SMatthew G. Knepley @*/ 2120d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap(DM dm, DM dmSrc, PetscInt overlap) 2121d71ae5a4SJacob Faibussowitsch { 2122c506a872SMatthew G. Knepley PetscFunctionBegin; 2123c506a872SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2124c506a872SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 3); 2125c506a872SMatthew G. Knepley PetscTryMethod(dm, "DMPlexSetOverlap_C", (DM, DM, PetscInt), (dm, dmSrc, overlap)); 21263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2127c506a872SMatthew G. Knepley } 2128c506a872SMatthew G. Knepley 2129d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault_Plex(DM dm, PetscBool dist) 2130d71ae5a4SJacob Faibussowitsch { 2131e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2132e600fa54SMatthew G. Knepley 2133e600fa54SMatthew G. Knepley PetscFunctionBegin; 2134e600fa54SMatthew G. Knepley mesh->distDefault = dist; 21353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2136e600fa54SMatthew G. Knepley } 2137e600fa54SMatthew G. Knepley 2138e600fa54SMatthew G. Knepley /*@ 213920f4b53cSBarry Smith DMPlexDistributeSetDefault - Set flag indicating whether the `DM` should be distributed by default 2140e600fa54SMatthew G. Knepley 214120f4b53cSBarry Smith Logically Collective 2142e600fa54SMatthew G. Knepley 2143e600fa54SMatthew G. Knepley Input Parameters: 214420f4b53cSBarry Smith + dm - The `DM` 2145e600fa54SMatthew G. Knepley - dist - Flag for distribution 2146e600fa54SMatthew G. Knepley 2147e600fa54SMatthew G. Knepley Level: intermediate 2148e600fa54SMatthew G. Knepley 214920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributeGetDefault()`, `DMPlexDistribute()` 2150e600fa54SMatthew G. Knepley @*/ 2151d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault(DM dm, PetscBool dist) 2152d71ae5a4SJacob Faibussowitsch { 2153e600fa54SMatthew G. Knepley PetscFunctionBegin; 2154e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2155e600fa54SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, dist, 2); 2156cac4c232SBarry Smith PetscTryMethod(dm, "DMPlexDistributeSetDefault_C", (DM, PetscBool), (dm, dist)); 21573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2158e600fa54SMatthew G. Knepley } 2159e600fa54SMatthew G. Knepley 2160d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault_Plex(DM dm, PetscBool *dist) 2161d71ae5a4SJacob Faibussowitsch { 2162e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2163e600fa54SMatthew G. Knepley 2164e600fa54SMatthew G. Knepley PetscFunctionBegin; 2165e600fa54SMatthew G. Knepley *dist = mesh->distDefault; 21663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2167e600fa54SMatthew G. Knepley } 2168e600fa54SMatthew G. Knepley 2169e600fa54SMatthew G. Knepley /*@ 217020f4b53cSBarry Smith DMPlexDistributeGetDefault - Get flag indicating whether the `DM` should be distributed by default 2171e600fa54SMatthew G. Knepley 217220f4b53cSBarry Smith Not Collective 2173e600fa54SMatthew G. Knepley 2174e600fa54SMatthew G. Knepley Input Parameter: 217520f4b53cSBarry Smith . dm - The `DM` 2176e600fa54SMatthew G. Knepley 2177e600fa54SMatthew G. Knepley Output Parameter: 2178e600fa54SMatthew G. Knepley . dist - Flag for distribution 2179e600fa54SMatthew G. Knepley 2180e600fa54SMatthew G. Knepley Level: intermediate 2181e600fa54SMatthew G. Knepley 218220f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexDistributeSetDefault()`, `DMPlexDistribute()` 2183e600fa54SMatthew G. Knepley @*/ 2184d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault(DM dm, PetscBool *dist) 2185d71ae5a4SJacob Faibussowitsch { 2186e600fa54SMatthew G. Knepley PetscFunctionBegin; 2187e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21884f572ea9SToby Isaac PetscAssertPointer(dist, 2); 2189cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexDistributeGetDefault_C", (DM, PetscBool *), (dm, dist)); 21903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2191e600fa54SMatthew G. Knepley } 2192e600fa54SMatthew G. Knepley 21936462276dSToby Isaac /*@C 219420f4b53cSBarry Smith DMPlexGetGatherDM - Get a copy of the `DMPLEX` that gathers all points on the 21956462276dSToby Isaac root process of the original's communicator. 21966462276dSToby Isaac 219720f4b53cSBarry Smith Collective 219883655b49SVáclav Hapla 2199064ec1f3Sprj- Input Parameter: 220020f4b53cSBarry Smith . dm - the original `DMPLEX` object 22016462276dSToby Isaac 22026462276dSToby Isaac Output Parameters: 220320f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional) 220420f4b53cSBarry Smith - gatherMesh - the gathered `DM` object, or `NULL` 22056462276dSToby Isaac 22066462276dSToby Isaac Level: intermediate 22076462276dSToby Isaac 220820f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `PetscSF`, `DMPlexDistribute()`, `DMPlexGetRedundantDM()` 22096462276dSToby Isaac @*/ 2210d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetGatherDM(DM dm, PetscSF *sf, DM *gatherMesh) 2211d71ae5a4SJacob Faibussowitsch { 22126462276dSToby Isaac MPI_Comm comm; 22136462276dSToby Isaac PetscMPIInt size; 22146462276dSToby Isaac PetscPartitioner oldPart, gatherPart; 22156462276dSToby Isaac 22166462276dSToby Isaac PetscFunctionBegin; 22176462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22184f572ea9SToby Isaac PetscAssertPointer(gatherMesh, 3); 22190c86c063SLisandro Dalcin *gatherMesh = NULL; 2220a13df41bSStefano Zampini if (sf) *sf = NULL; 22216462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 22229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 22233ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 22249566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &oldPart)); 22259566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)oldPart)); 22269566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(comm, &gatherPart)); 22279566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetType(gatherPart, PETSCPARTITIONERGATHER)); 22289566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, gatherPart)); 22299566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, sf, gatherMesh)); 2230a13df41bSStefano Zampini 22319566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, oldPart)); 22329566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&gatherPart)); 22339566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&oldPart)); 22343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22356462276dSToby Isaac } 22366462276dSToby Isaac 22376462276dSToby Isaac /*@C 223820f4b53cSBarry Smith DMPlexGetRedundantDM - Get a copy of the `DMPLEX` that is completely copied on each process. 22396462276dSToby Isaac 224020f4b53cSBarry Smith Collective 224183655b49SVáclav Hapla 2242064ec1f3Sprj- Input Parameter: 224320f4b53cSBarry Smith . dm - the original `DMPLEX` object 22446462276dSToby Isaac 22456462276dSToby Isaac Output Parameters: 224620f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional) 224720f4b53cSBarry Smith - redundantMesh - the redundant `DM` object, or `NULL` 22486462276dSToby Isaac 22496462276dSToby Isaac Level: intermediate 22506462276dSToby Isaac 225160225df5SJacob Faibussowitsch .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetGatherDM()` 22526462276dSToby Isaac @*/ 2253d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRedundantDM(DM dm, PetscSF *sf, DM *redundantMesh) 2254d71ae5a4SJacob Faibussowitsch { 22556462276dSToby Isaac MPI_Comm comm; 22566462276dSToby Isaac PetscMPIInt size, rank; 22576462276dSToby Isaac PetscInt pStart, pEnd, p; 22586462276dSToby Isaac PetscInt numPoints = -1; 2259a13df41bSStefano Zampini PetscSF migrationSF, sfPoint, gatherSF; 22606462276dSToby Isaac DM gatherDM, dmCoord; 22616462276dSToby Isaac PetscSFNode *points; 22626462276dSToby Isaac 22636462276dSToby Isaac PetscFunctionBegin; 22646462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22654f572ea9SToby Isaac PetscAssertPointer(redundantMesh, 3); 22660c86c063SLisandro Dalcin *redundantMesh = NULL; 22676462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 22689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 226968dbc166SMatthew G. Knepley if (size == 1) { 22709566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 227168dbc166SMatthew G. Knepley *redundantMesh = dm; 2272a13df41bSStefano Zampini if (sf) *sf = NULL; 22733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 227468dbc166SMatthew G. Knepley } 22759566063dSJacob Faibussowitsch PetscCall(DMPlexGetGatherDM(dm, &gatherSF, &gatherDM)); 22763ba16761SJacob Faibussowitsch if (!gatherDM) PetscFunctionReturn(PETSC_SUCCESS); 22779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 22789566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(gatherDM, &pStart, &pEnd)); 22796462276dSToby Isaac numPoints = pEnd - pStart; 22809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numPoints, 1, MPIU_INT, 0, comm)); 22819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &points)); 22829566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &migrationSF)); 22836462276dSToby Isaac for (p = 0; p < numPoints; p++) { 22846462276dSToby Isaac points[p].index = p; 22856462276dSToby Isaac points[p].rank = 0; 22866462276dSToby Isaac } 22879566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(migrationSF, pEnd - pStart, numPoints, NULL, PETSC_OWN_POINTER, points, PETSC_OWN_POINTER)); 22889566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, redundantMesh)); 22899566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*redundantMesh, "Redundant Mesh")); 22909566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(gatherDM, migrationSF, *redundantMesh)); 22912e28cf0cSVaclav Hapla /* This is to express that all point are in overlap */ 22922e28cf0cSVaclav Hapla PetscCall(DMPlexSetOverlap_Plex(*redundantMesh, NULL, PETSC_MAX_INT)); 22939566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*redundantMesh, migrationSF, PETSC_FALSE, &sfPoint)); 22949566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*redundantMesh, sfPoint)); 22959566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*redundantMesh, &dmCoord)); 22969566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 22979566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 2298a13df41bSStefano Zampini if (sf) { 2299a13df41bSStefano Zampini PetscSF tsf; 2300a13df41bSStefano Zampini 23019566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(gatherSF, migrationSF, &tsf)); 23029566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, tsf, sf)); 23039566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&tsf)); 2304a13df41bSStefano Zampini } 23059566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&migrationSF)); 23069566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&gatherSF)); 23079566063dSJacob Faibussowitsch PetscCall(DMDestroy(&gatherDM)); 23089566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *redundantMesh)); 23095de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *redundantMesh)); 23103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23116462276dSToby Isaac } 23125fa78c88SVaclav Hapla 23135fa78c88SVaclav Hapla /*@ 231420f4b53cSBarry Smith DMPlexIsDistributed - Find out whether this `DM` is distributed, i.e. more than one rank owns some points. 23155fa78c88SVaclav Hapla 23165fa78c88SVaclav Hapla Collective 23175fa78c88SVaclav Hapla 23185fa78c88SVaclav Hapla Input Parameter: 231920f4b53cSBarry Smith . dm - The `DM` object 23205fa78c88SVaclav Hapla 23215fa78c88SVaclav Hapla Output Parameter: 232220f4b53cSBarry Smith . distributed - Flag whether the `DM` is distributed 23235fa78c88SVaclav Hapla 23245fa78c88SVaclav Hapla Level: intermediate 23255fa78c88SVaclav Hapla 23265fa78c88SVaclav Hapla Notes: 23275fa78c88SVaclav Hapla This currently finds out whether at least two ranks have any DAG points. 232820f4b53cSBarry Smith This involves `MPI_Allreduce()` with one integer. 23295fa78c88SVaclav Hapla The result is currently not stashed so every call to this routine involves this global communication. 23305fa78c88SVaclav Hapla 233160225df5SJacob Faibussowitsch .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetOverlap()`, `DMPlexIsInterpolated()` 23325fa78c88SVaclav Hapla @*/ 2333d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsDistributed(DM dm, PetscBool *distributed) 2334d71ae5a4SJacob Faibussowitsch { 23355fa78c88SVaclav Hapla PetscInt pStart, pEnd, count; 23365fa78c88SVaclav Hapla MPI_Comm comm; 233735d70e31SStefano Zampini PetscMPIInt size; 23385fa78c88SVaclav Hapla 23395fa78c88SVaclav Hapla PetscFunctionBegin; 23405fa78c88SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23414f572ea9SToby Isaac PetscAssertPointer(distributed, 2); 23429566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 23439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 23449371c9d4SSatish Balay if (size == 1) { 23459371c9d4SSatish Balay *distributed = PETSC_FALSE; 23463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23479371c9d4SSatish Balay } 23489566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 234935d70e31SStefano Zampini count = (pEnd - pStart) > 0 ? 1 : 0; 2350712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &count, 1, MPIU_INT, MPI_SUM, comm)); 23515fa78c88SVaclav Hapla *distributed = count > 1 ? PETSC_TRUE : PETSC_FALSE; 23523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23535fa78c88SVaclav Hapla } 23541d1f2f2aSksagiyam 23551d1f2f2aSksagiyam /*@C 23561d1f2f2aSksagiyam DMPlexDistributionSetName - Set the name of the specific parallel distribution 23571d1f2f2aSksagiyam 23581d1f2f2aSksagiyam Input Parameters: 235920f4b53cSBarry Smith + dm - The `DM` 23601d1f2f2aSksagiyam - name - The name of the specific parallel distribution 23611d1f2f2aSksagiyam 23621d1f2f2aSksagiyam Level: developer 23631d1f2f2aSksagiyam 236420f4b53cSBarry Smith Note: 236520f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's 236620f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under 236720f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()` 236820f4b53cSBarry Smith loads the parallel distribution stored in file under this name. 236920f4b53cSBarry Smith 237020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionGetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()` 23711d1f2f2aSksagiyam @*/ 2372d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionSetName(DM dm, const char name[]) 2373d71ae5a4SJacob Faibussowitsch { 23741d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data; 23751d1f2f2aSksagiyam 23761d1f2f2aSksagiyam PetscFunctionBegin; 23771d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 23784f572ea9SToby Isaac if (name) PetscAssertPointer(name, 2); 23791d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 23801d1f2f2aSksagiyam PetscCall(PetscStrallocpy(name, &mesh->distributionName)); 23813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23821d1f2f2aSksagiyam } 23831d1f2f2aSksagiyam 23841d1f2f2aSksagiyam /*@C 23851d1f2f2aSksagiyam DMPlexDistributionGetName - Retrieve the name of the specific parallel distribution 23861d1f2f2aSksagiyam 23871d1f2f2aSksagiyam Input Parameter: 238820f4b53cSBarry Smith . dm - The `DM` 23891d1f2f2aSksagiyam 23901d1f2f2aSksagiyam Output Parameter: 23911d1f2f2aSksagiyam . name - The name of the specific parallel distribution 23921d1f2f2aSksagiyam 23931d1f2f2aSksagiyam Level: developer 23941d1f2f2aSksagiyam 239520f4b53cSBarry Smith Note: 239620f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's 239720f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under 239820f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()` 239920f4b53cSBarry Smith loads the parallel distribution stored in file under this name. 240020f4b53cSBarry Smith 240120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionSetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()` 24021d1f2f2aSksagiyam @*/ 2403d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionGetName(DM dm, const char *name[]) 2404d71ae5a4SJacob Faibussowitsch { 24051d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data; 24061d1f2f2aSksagiyam 24071d1f2f2aSksagiyam PetscFunctionBegin; 24081d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 24094f572ea9SToby Isaac PetscAssertPointer(name, 2); 24101d1f2f2aSksagiyam *name = mesh->distributionName; 24113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24121d1f2f2aSksagiyam } 2413