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) { 20124c766afSToby Isaac PetscInt depth, coneSeries, supportSeries, maxC, maxS, 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)); 20724c766afSToby Isaac coneSeries = (maxC > 1) ? ((PetscPowInt(maxC, depth + 1) - 1) / (maxC - 1)) : depth + 1; 20824c766afSToby Isaac supportSeries = (maxS > 1) ? ((PetscPowInt(maxS, depth + 1) - 1) / (maxS - 1)) : depth + 1; 20924c766afSToby Isaac asiz = PetscMax(PetscPowInt(maxS, depth) * coneSeries, PetscPowInt(maxC, depth) * supportSeries); 2108b0b4c70SToby Isaac asiz *= maxAnchors; 21124c766afSToby Isaac asiz = PetscMin(asiz, pEnd - pStart); 2129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(asiz, adj)); 21379bad331SMatthew G. Knepley } 21479bad331SMatthew G. Knepley if (*adjSize < 0) *adjSize = asiz; 2158b0b4c70SToby Isaac maxAdjSize = *adjSize; 2163c1f0c11SLawrence Mitchell if (mesh->useradjacency) { 2179566063dSJacob Faibussowitsch PetscCall((*mesh->useradjacency)(dm, p, adjSize, *adj, mesh->useradjacencyctx)); 2183c1f0c11SLawrence Mitchell } else if (useTransitiveClosure) { 2199566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Transitive_Internal(dm, p, useCone, adjSize, *adj)); 22070034214SMatthew G. Knepley } else if (useCone) { 2219566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Cone_Internal(dm, p, adjSize, *adj)); 22270034214SMatthew G. Knepley } else { 2239566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Support_Internal(dm, p, adjSize, *adj)); 22470034214SMatthew G. Knepley } 2255b317d89SToby Isaac if (useAnchors && aSec) { 2268b0b4c70SToby Isaac PetscInt origSize = *adjSize; 2278b0b4c70SToby Isaac PetscInt numAdj = origSize; 2288b0b4c70SToby Isaac PetscInt i = 0, j; 2298b0b4c70SToby Isaac PetscInt *orig = *adj; 2308b0b4c70SToby Isaac 2318b0b4c70SToby Isaac while (i < origSize) { 2328b0b4c70SToby Isaac PetscInt p = orig[i]; 2338b0b4c70SToby Isaac PetscInt aDof = 0; 2348b0b4c70SToby Isaac 23548a46eb9SPierre Jolivet if (p >= aStart && p < aEnd) PetscCall(PetscSectionGetDof(aSec, p, &aDof)); 2368b0b4c70SToby Isaac if (aDof) { 2378b0b4c70SToby Isaac PetscInt aOff; 2388b0b4c70SToby Isaac PetscInt s, q; 2398b0b4c70SToby Isaac 240ad540459SPierre Jolivet for (j = i + 1; j < numAdj; j++) orig[j - 1] = orig[j]; 2418b0b4c70SToby Isaac origSize--; 2428b0b4c70SToby Isaac numAdj--; 2439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff)); 2448b0b4c70SToby Isaac for (s = 0; s < aDof; ++s) { 245527e7439SSatish Balay for (q = 0; q < numAdj || ((void)(orig[numAdj++] = anchors[aOff + s]), 0); ++q) { 2468b0b4c70SToby Isaac if (anchors[aOff + s] == orig[q]) break; 2478b0b4c70SToby Isaac } 24863a3b9bcSJacob Faibussowitsch PetscCheck(numAdj <= maxAdjSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%" PetscInt_FMT ")", maxAdjSize); 2498b0b4c70SToby Isaac } 2509371c9d4SSatish Balay } else { 2518b0b4c70SToby Isaac i++; 2528b0b4c70SToby Isaac } 2538b0b4c70SToby Isaac } 2548b0b4c70SToby Isaac *adjSize = numAdj; 2559566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 2568b0b4c70SToby Isaac } 2573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25870034214SMatthew G. Knepley } 25970034214SMatthew G. Knepley 26070034214SMatthew G. Knepley /*@ 26170034214SMatthew G. Knepley DMPlexGetAdjacency - Return all points adjacent to the given point 26270034214SMatthew G. Knepley 26370034214SMatthew G. Knepley Input Parameters: 26420f4b53cSBarry Smith + dm - The `DM` object 2656b867d5aSJose E. Roman - p - The point 26670034214SMatthew G. Knepley 2676b867d5aSJose E. Roman Input/Output Parameters: 26820f4b53cSBarry Smith + adjSize - The maximum size of `adj` if it is non-`NULL`, or `PETSC_DETERMINE`; 2696b867d5aSJose E. Roman on output the number of adjacent points 27020f4b53cSBarry Smith - adj - Either `NULL` so that the array is allocated, or an existing array with size `adjSize`; 2716b867d5aSJose E. Roman on output contains the adjacent points 27270034214SMatthew G. Knepley 27370034214SMatthew G. Knepley Level: advanced 27470034214SMatthew G. Knepley 27595452b02SPatrick Sanan Notes: 27620f4b53cSBarry Smith The user must `PetscFree()` the `adj` array if it was not passed in. 27770034214SMatthew G. Knepley 27820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMCreateMatrix()`, `DMPlexPreallocateOperator()` 27970034214SMatthew G. Knepley @*/ 280d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAdjacency(DM dm, PetscInt p, PetscInt *adjSize, PetscInt *adj[]) 281d71ae5a4SJacob Faibussowitsch { 2821cf84007SMatthew G. Knepley PetscBool useCone, useClosure, useAnchors; 28370034214SMatthew G. Knepley 28470034214SMatthew G. Knepley PetscFunctionBeginHot; 28570034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2864f572ea9SToby Isaac PetscAssertPointer(adjSize, 3); 2874f572ea9SToby Isaac PetscAssertPointer(adj, 4); 2889566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 2899566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors)); 2909566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, adjSize, adj)); 2913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29270034214SMatthew G. Knepley } 29308633170SToby Isaac 294b0a623aaSMatthew G. Knepley /*@ 29520f4b53cSBarry Smith DMPlexCreateTwoSidedProcessSF - Create an `PetscSF` which just has process connectivity 296b0a623aaSMatthew G. Knepley 29720f4b53cSBarry Smith Collective 298b0a623aaSMatthew G. Knepley 299b0a623aaSMatthew G. Knepley Input Parameters: 30020f4b53cSBarry Smith + dm - The `DM` 30120f4b53cSBarry Smith . sfPoint - The `PetscSF` which encodes point connectivity 30220f4b53cSBarry Smith . rootRankSection - to be documented 30320f4b53cSBarry Smith . rootRanks - to be documented 30460225df5SJacob Faibussowitsch . leafRankSection - to be documented 30520f4b53cSBarry Smith - leafRanks - to be documented 306b0a623aaSMatthew G. Knepley 307b0a623aaSMatthew G. Knepley Output Parameters: 30820f4b53cSBarry Smith + processRanks - A list of process neighbors, or `NULL` 30920f4b53cSBarry Smith - sfProcess - An `PetscSF` encoding the two-sided process connectivity, or `NULL` 310b0a623aaSMatthew G. Knepley 311b0a623aaSMatthew G. Knepley Level: developer 312b0a623aaSMatthew G. Knepley 31320f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSFCreate()`, `DMPlexCreateProcessSF()` 314b0a623aaSMatthew G. Knepley @*/ 315d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateTwoSidedProcessSF(DM dm, PetscSF sfPoint, PetscSection rootRankSection, IS rootRanks, PetscSection leafRankSection, IS leafRanks, IS *processRanks, PetscSF *sfProcess) 316d71ae5a4SJacob Faibussowitsch { 317b0a623aaSMatthew G. Knepley const PetscSFNode *remotePoints; 318b0a623aaSMatthew G. Knepley PetscInt *localPointsNew; 319b0a623aaSMatthew G. Knepley PetscSFNode *remotePointsNew; 320b0a623aaSMatthew G. Knepley const PetscInt *nranks; 321b0a623aaSMatthew G. Knepley PetscInt *ranksNew; 322b0a623aaSMatthew G. Knepley PetscBT neighbors; 323b0a623aaSMatthew G. Knepley PetscInt pStart, pEnd, p, numLeaves, l, numNeighbors, n; 3249852e123SBarry Smith PetscMPIInt size, proc, rank; 325b0a623aaSMatthew G. Knepley 326b0a623aaSMatthew G. Knepley PetscFunctionBegin; 327b0a623aaSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 328b0a623aaSMatthew G. Knepley PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2); 3294f572ea9SToby Isaac if (processRanks) PetscAssertPointer(processRanks, 7); 3304f572ea9SToby Isaac if (sfProcess) PetscAssertPointer(sfProcess, 8); 3319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 3329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 3339566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &numLeaves, NULL, &remotePoints)); 3349566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(size, &neighbors)); 3359566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(size, neighbors)); 336b0a623aaSMatthew G. Knepley /* Compute root-to-leaf process connectivity */ 3379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(rootRankSection, &pStart, &pEnd)); 3389566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rootRanks, &nranks)); 339b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 340b0a623aaSMatthew G. Knepley PetscInt ndof, noff, n; 341b0a623aaSMatthew G. Knepley 3429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootRankSection, p, &ndof)); 3439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootRankSection, p, &noff)); 3449566063dSJacob Faibussowitsch for (n = 0; n < ndof; ++n) PetscCall(PetscBTSet(neighbors, nranks[noff + n])); 345b0a623aaSMatthew G. Knepley } 3469566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rootRanks, &nranks)); 347b0a623aaSMatthew G. Knepley /* Compute leaf-to-neighbor process connectivity */ 3489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafRankSection, &pStart, &pEnd)); 3499566063dSJacob Faibussowitsch PetscCall(ISGetIndices(leafRanks, &nranks)); 350b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 351b0a623aaSMatthew G. Knepley PetscInt ndof, noff, n; 352b0a623aaSMatthew G. Knepley 3539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafRankSection, p, &ndof)); 3549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafRankSection, p, &noff)); 3559566063dSJacob Faibussowitsch for (n = 0; n < ndof; ++n) PetscCall(PetscBTSet(neighbors, nranks[noff + n])); 356b0a623aaSMatthew G. Knepley } 3579566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(leafRanks, &nranks)); 358b0a623aaSMatthew G. Knepley /* Compute leaf-to-root process connectivity */ 3593ba16761SJacob Faibussowitsch for (l = 0; l < numLeaves; ++l) PetscCall(PetscBTSet(neighbors, remotePoints[l].rank)); 360b0a623aaSMatthew G. Knepley /* Calculate edges */ 3613ba16761SJacob Faibussowitsch PetscCall(PetscBTClear(neighbors, rank)); 3629371c9d4SSatish Balay for (proc = 0, numNeighbors = 0; proc < size; ++proc) { 3639371c9d4SSatish Balay if (PetscBTLookup(neighbors, proc)) ++numNeighbors; 3649371c9d4SSatish Balay } 3659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNeighbors, &ranksNew)); 3669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNeighbors, &localPointsNew)); 3679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numNeighbors, &remotePointsNew)); 3689852e123SBarry Smith for (proc = 0, n = 0; proc < size; ++proc) { 369b0a623aaSMatthew G. Knepley if (PetscBTLookup(neighbors, proc)) { 370b0a623aaSMatthew G. Knepley ranksNew[n] = proc; 371b0a623aaSMatthew G. Knepley localPointsNew[n] = proc; 372b0a623aaSMatthew G. Knepley remotePointsNew[n].index = rank; 373b0a623aaSMatthew G. Knepley remotePointsNew[n].rank = proc; 374b0a623aaSMatthew G. Knepley ++n; 375b0a623aaSMatthew G. Knepley } 376b0a623aaSMatthew G. Knepley } 3779566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&neighbors)); 3789566063dSJacob Faibussowitsch if (processRanks) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), numNeighbors, ranksNew, PETSC_OWN_POINTER, processRanks)); 3799566063dSJacob Faibussowitsch else PetscCall(PetscFree(ranksNew)); 380b0a623aaSMatthew G. Knepley if (sfProcess) { 3819566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess)); 3829566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*sfProcess, "Two-Sided Process SF")); 3839566063dSJacob Faibussowitsch PetscCall(PetscSFSetFromOptions(*sfProcess)); 3849566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sfProcess, size, numNeighbors, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER)); 385b0a623aaSMatthew G. Knepley } 3863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 387b0a623aaSMatthew G. Knepley } 388b0a623aaSMatthew G. Knepley 389b0a623aaSMatthew G. Knepley /*@ 390b0a623aaSMatthew G. Knepley DMPlexDistributeOwnership - Compute owner information for shared points. This basically gets two-sided for an SF. 391b0a623aaSMatthew G. Knepley 39220f4b53cSBarry Smith Collective 393b0a623aaSMatthew G. Knepley 394b0a623aaSMatthew G. Knepley Input Parameter: 39520f4b53cSBarry Smith . dm - The `DM` 396b0a623aaSMatthew G. Knepley 397b0a623aaSMatthew G. Knepley Output Parameters: 398b0a623aaSMatthew G. Knepley + rootSection - The number of leaves for a given root point 399b0a623aaSMatthew G. Knepley . rootrank - The rank of each edge into the root point 400b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point 401b0a623aaSMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point 402b0a623aaSMatthew G. Knepley 403b0a623aaSMatthew G. Knepley Level: developer 404b0a623aaSMatthew G. Knepley 40520f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabel()`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 406b0a623aaSMatthew G. Knepley @*/ 407d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeOwnership(DM dm, PetscSection rootSection, IS *rootrank, PetscSection leafSection, IS *leafrank) 408d71ae5a4SJacob Faibussowitsch { 409b0a623aaSMatthew G. Knepley MPI_Comm comm; 410b0a623aaSMatthew G. Knepley PetscSF sfPoint; 411b0a623aaSMatthew G. Knepley const PetscInt *rootdegree; 412b0a623aaSMatthew G. Knepley PetscInt *myrank, *remoterank; 413b0a623aaSMatthew G. Knepley PetscInt pStart, pEnd, p, nedges; 414b0a623aaSMatthew G. Knepley PetscMPIInt rank; 415b0a623aaSMatthew G. Knepley 416b0a623aaSMatthew G. Knepley PetscFunctionBegin; 4179566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 4199566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4209566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 421b0a623aaSMatthew G. Knepley /* Compute number of leaves for each root */ 4229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rootSection, "Root Section")); 4239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection, pStart, pEnd)); 4249566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(sfPoint, &rootdegree)); 4259566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(sfPoint, &rootdegree)); 4269566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(rootSection, p, rootdegree[p - pStart])); 4279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection)); 428b0a623aaSMatthew G. Knepley /* Gather rank of each leaf to root */ 4299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &nedges)); 4309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &myrank)); 4319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nedges, &remoterank)); 432b0a623aaSMatthew G. Knepley for (p = 0; p < pEnd - pStart; ++p) myrank[p] = rank; 4339566063dSJacob Faibussowitsch PetscCall(PetscSFGatherBegin(sfPoint, MPIU_INT, myrank, remoterank)); 4349566063dSJacob Faibussowitsch PetscCall(PetscSFGatherEnd(sfPoint, MPIU_INT, myrank, remoterank)); 4359566063dSJacob Faibussowitsch PetscCall(PetscFree(myrank)); 4369566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, nedges, remoterank, PETSC_OWN_POINTER, rootrank)); 437b0a623aaSMatthew G. Knepley /* Distribute remote ranks to leaves */ 4389566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)leafSection, "Leaf Section")); 4399566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeFieldIS(dm, sfPoint, rootSection, *rootrank, leafSection, leafrank)); 4403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 441b0a623aaSMatthew G. Knepley } 442b0a623aaSMatthew G. Knepley 443278397a0SMatthew G. Knepley /*@C 444c506a872SMatthew G. Knepley DMPlexCreateOverlapLabel - Compute a label indicating what overlap points should be sent to new processes 445b0a623aaSMatthew G. Knepley 44620f4b53cSBarry Smith Collective 447b0a623aaSMatthew G. Knepley 448b0a623aaSMatthew G. Knepley Input Parameters: 44920f4b53cSBarry Smith + dm - The `DM` 45024d039d7SMichael Lange . levels - Number of overlap levels 451b0a623aaSMatthew G. Knepley . rootSection - The number of leaves for a given root point 452b0a623aaSMatthew G. Knepley . rootrank - The rank of each edge into the root point 453b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point 454b0a623aaSMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point 455b0a623aaSMatthew G. Knepley 456064ec1f3Sprj- Output Parameter: 45720f4b53cSBarry Smith . ovLabel - `DMLabel` containing remote overlap contributions as point/rank pairings 458b0a623aaSMatthew G. Knepley 459b0a623aaSMatthew G. Knepley Level: developer 460b0a623aaSMatthew G. Knepley 46120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabelFromLabels()`, `DMPlexGetAdjacency()`, `DMPlexDistributeOwnership()`, `DMPlexDistribute()` 462b0a623aaSMatthew G. Knepley @*/ 463d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateOverlapLabel(DM dm, PetscInt levels, PetscSection rootSection, IS rootrank, PetscSection leafSection, IS leafrank, DMLabel *ovLabel) 464d71ae5a4SJacob Faibussowitsch { 465e540f424SMichael Lange MPI_Comm comm; 466b0a623aaSMatthew G. Knepley DMLabel ovAdjByRank; /* A DMLabel containing all points adjacent to shared points, separated by rank (value in label) */ 467874ddda9SLisandro Dalcin PetscSF sfPoint; 468b0a623aaSMatthew G. Knepley const PetscSFNode *remote; 469b0a623aaSMatthew G. Knepley const PetscInt *local; 4701fd9873aSMichael Lange const PetscInt *nrank, *rrank; 471b0a623aaSMatthew G. Knepley PetscInt *adj = NULL; 4721fd9873aSMichael Lange PetscInt pStart, pEnd, p, sStart, sEnd, nleaves, l; 4739852e123SBarry Smith PetscMPIInt rank, size; 47431bc6364SLisandro Dalcin PetscBool flg; 475b0a623aaSMatthew G. Knepley 476b0a623aaSMatthew G. Knepley PetscFunctionBegin; 4776ba1a4c7SVaclav Hapla *ovLabel = NULL; 4789566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 4809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 4813ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 4829566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 4839566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 484d1674c6dSMatthew Knepley if (!levels) { 485d1674c6dSMatthew Knepley /* Add owned points */ 4869566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel)); 4879566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) PetscCall(DMLabelSetValue(*ovLabel, p, rank)); 4883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 489d1674c6dSMatthew Knepley } 4909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafSection, &sStart, &sEnd)); 4919566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote)); 4929566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap adjacency", &ovAdjByRank)); 493b0a623aaSMatthew G. Knepley /* Handle leaves: shared with the root point */ 494b0a623aaSMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 495b0a623aaSMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a; 496b0a623aaSMatthew G. Knepley 4979566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, local ? local[l] : l, &adjSize, &adj)); 4989566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remote[l].rank)); 499b0a623aaSMatthew G. Knepley } 5009566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rootrank, &rrank)); 5019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(leafrank, &nrank)); 502b0a623aaSMatthew G. Knepley /* Handle roots */ 503b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 504b0a623aaSMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, neighbors = 0, noff, n, a; 505b0a623aaSMatthew G. Knepley 506b0a623aaSMatthew G. Knepley if ((p >= sStart) && (p < sEnd)) { 507b0a623aaSMatthew G. Knepley /* Some leaves share a root with other leaves on different processes */ 5089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, p, &neighbors)); 509b0a623aaSMatthew G. Knepley if (neighbors) { 5109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafSection, p, &noff)); 5119566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 512b0a623aaSMatthew G. Knepley for (n = 0; n < neighbors; ++n) { 513b0a623aaSMatthew G. Knepley const PetscInt remoteRank = nrank[noff + n]; 514b0a623aaSMatthew G. Knepley 515b0a623aaSMatthew G. Knepley if (remoteRank == rank) continue; 5169566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 517b0a623aaSMatthew G. Knepley } 518b0a623aaSMatthew G. Knepley } 519b0a623aaSMatthew G. Knepley } 520b0a623aaSMatthew G. Knepley /* Roots are shared with leaves */ 5219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootSection, p, &neighbors)); 522b0a623aaSMatthew G. Knepley if (!neighbors) continue; 5239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection, p, &noff)); 5249566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 525b0a623aaSMatthew G. Knepley for (n = 0; n < neighbors; ++n) { 526b0a623aaSMatthew G. Knepley const PetscInt remoteRank = rrank[noff + n]; 527b0a623aaSMatthew G. Knepley 528b0a623aaSMatthew G. Knepley if (remoteRank == rank) continue; 5299566063dSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 530b0a623aaSMatthew G. Knepley } 531b0a623aaSMatthew G. Knepley } 5329566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 5339566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(rootrank, &rrank)); 5349566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(leafrank, &nrank)); 53524d039d7SMichael Lange /* Add additional overlap levels */ 536be200f8dSMichael Lange for (l = 1; l < levels; l++) { 537be200f8dSMichael Lange /* Propagate point donations over SF to capture remote connections */ 5389566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelPropagate(dm, ovAdjByRank)); 539be200f8dSMichael Lange /* Add next level of point donations to the label */ 5409566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelAdjacency(dm, ovAdjByRank)); 541be200f8dSMichael Lange } 54226a7d390SMatthew G. Knepley /* We require the closure in the overlap */ 5439566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelClosure(dm, ovAdjByRank)); 5449566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-overlap_view", &flg)); 545e540f424SMichael Lange if (flg) { 546825f8a23SLisandro Dalcin PetscViewer viewer; 5479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &viewer)); 5489566063dSJacob Faibussowitsch PetscCall(DMLabelView(ovAdjByRank, viewer)); 549b0a623aaSMatthew G. Knepley } 550874ddda9SLisandro Dalcin /* Invert sender to receiver label */ 5519566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel)); 5529566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelInvert(dm, ovAdjByRank, NULL, *ovLabel)); 553a9f1d5b2SMichael Lange /* Add owned points, except for shared local points */ 5549566063dSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) PetscCall(DMLabelSetValue(*ovLabel, p, rank)); 555e540f424SMichael Lange for (l = 0; l < nleaves; ++l) { 5569566063dSJacob Faibussowitsch PetscCall(DMLabelClearValue(*ovLabel, local[l], rank)); 5579566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(*ovLabel, remote[l].index, remote[l].rank)); 558e540f424SMichael Lange } 559e540f424SMichael Lange /* Clean up */ 5609566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&ovAdjByRank)); 5613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 562b0a623aaSMatthew G. Knepley } 56370034214SMatthew G. Knepley 564d71ae5a4SJacob Faibussowitsch static PetscErrorCode HandlePoint_Private(DM dm, PetscInt p, PetscSection section, const PetscInt ranks[], PetscInt numExLabels, const DMLabel exLabel[], const PetscInt exValue[], DMLabel ovAdjByRank) 565d71ae5a4SJacob Faibussowitsch { 566c506a872SMatthew G. Knepley PetscInt neighbors, el; 567c506a872SMatthew G. Knepley 568c506a872SMatthew G. Knepley PetscFunctionBegin; 569c506a872SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, p, &neighbors)); 570c506a872SMatthew G. Knepley if (neighbors) { 571c506a872SMatthew G. Knepley PetscInt *adj = NULL; 572c506a872SMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, noff, n, a; 573c506a872SMatthew G. Knepley PetscMPIInt rank; 574c506a872SMatthew G. Knepley 575c506a872SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 576c506a872SMatthew G. Knepley PetscCall(PetscSectionGetOffset(section, p, &noff)); 577c506a872SMatthew G. Knepley PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 578c506a872SMatthew G. Knepley for (n = 0; n < neighbors; ++n) { 579c506a872SMatthew G. Knepley const PetscInt remoteRank = ranks[noff + n]; 580c506a872SMatthew G. Knepley 581c506a872SMatthew G. Knepley if (remoteRank == rank) continue; 582c506a872SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 583c506a872SMatthew G. Knepley PetscBool insert = PETSC_TRUE; 584c506a872SMatthew G. Knepley 585c506a872SMatthew G. Knepley for (el = 0; el < numExLabels; ++el) { 586c506a872SMatthew G. Knepley PetscInt exVal; 587c506a872SMatthew G. Knepley PetscCall(DMLabelGetValue(exLabel[el], adj[a], &exVal)); 5889371c9d4SSatish Balay if (exVal == exValue[el]) { 5899371c9d4SSatish Balay insert = PETSC_FALSE; 5909371c9d4SSatish Balay break; 5919371c9d4SSatish Balay } 592c506a872SMatthew G. Knepley } 593c506a872SMatthew G. Knepley if (insert) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 594c506a872SMatthew G. Knepley } 595c506a872SMatthew G. Knepley } 596f88a03deSMatthew G. Knepley PetscCall(PetscFree(adj)); 597c506a872SMatthew G. Knepley } 5983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 599c506a872SMatthew G. Knepley } 600c506a872SMatthew G. Knepley 601c506a872SMatthew G. Knepley /*@C 602c506a872SMatthew G. Knepley DMPlexCreateOverlapLabelFromLabels - Compute a label indicating what overlap points should be sent to new processes 603c506a872SMatthew G. Knepley 60420f4b53cSBarry Smith Collective 605c506a872SMatthew G. Knepley 606c506a872SMatthew G. Knepley Input Parameters: 60720f4b53cSBarry Smith + dm - The `DM` 608c506a872SMatthew G. Knepley . numLabels - The number of labels to draw candidate points from 609c506a872SMatthew G. Knepley . label - An array of labels containing candidate points 610c506a872SMatthew G. Knepley . value - An array of label values marking the candidate points 611c506a872SMatthew G. Knepley . numExLabels - The number of labels to use for exclusion 61220f4b53cSBarry Smith . exLabel - An array of labels indicating points to be excluded, or `NULL` 61320f4b53cSBarry Smith . exValue - An array of label values to be excluded, or `NULL` 614c506a872SMatthew G. Knepley . rootSection - The number of leaves for a given root point 615c506a872SMatthew G. Knepley . rootrank - The rank of each edge into the root point 616c506a872SMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point 617c506a872SMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point 618c506a872SMatthew G. Knepley 619c506a872SMatthew G. Knepley Output Parameter: 62020f4b53cSBarry Smith . ovLabel - `DMLabel` containing remote overlap contributions as point/rank pairings 62120f4b53cSBarry Smith 62220f4b53cSBarry Smith Level: developer 623c506a872SMatthew G. Knepley 624c506a872SMatthew G. Knepley Note: 625c506a872SMatthew G. Knepley The candidate points are only added to the overlap if they are adjacent to a shared point 626c506a872SMatthew G. Knepley 62720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabel()`, `DMPlexGetAdjacency()`, `DMPlexDistributeOwnership()`, `DMPlexDistribute()` 628c506a872SMatthew G. Knepley @*/ 629d71ae5a4SJacob 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) 630d71ae5a4SJacob Faibussowitsch { 631c506a872SMatthew G. Knepley MPI_Comm comm; 632c506a872SMatthew G. Knepley DMLabel ovAdjByRank; /* A DMLabel containing all points adjacent to shared points, separated by rank (value in label) */ 633c506a872SMatthew G. Knepley PetscSF sfPoint; 634c506a872SMatthew G. Knepley const PetscSFNode *remote; 635c506a872SMatthew G. Knepley const PetscInt *local; 636c506a872SMatthew G. Knepley const PetscInt *nrank, *rrank; 637c506a872SMatthew G. Knepley PetscInt *adj = NULL; 638c506a872SMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, nleaves, l, el; 639c506a872SMatthew G. Knepley PetscMPIInt rank, size; 640c506a872SMatthew G. Knepley PetscBool flg; 641c506a872SMatthew G. Knepley 642c506a872SMatthew G. Knepley PetscFunctionBegin; 643c506a872SMatthew G. Knepley *ovLabel = NULL; 644c506a872SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 645c506a872SMatthew G. Knepley PetscCallMPI(MPI_Comm_size(comm, &size)); 646c506a872SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 6473ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 648c506a872SMatthew G. Knepley PetscCall(DMGetPointSF(dm, &sfPoint)); 649c506a872SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 650c506a872SMatthew G. Knepley PetscCall(PetscSectionGetChart(leafSection, &sStart, &sEnd)); 651c506a872SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote)); 652c506a872SMatthew G. Knepley PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap adjacency", &ovAdjByRank)); 653c506a872SMatthew G. Knepley PetscCall(ISGetIndices(rootrank, &rrank)); 654c506a872SMatthew G. Knepley PetscCall(ISGetIndices(leafrank, &nrank)); 655c506a872SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 656c506a872SMatthew G. Knepley IS valIS; 657c506a872SMatthew G. Knepley const PetscInt *points; 658c506a872SMatthew G. Knepley PetscInt n; 659c506a872SMatthew G. Knepley 660c506a872SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label[l], value[l], &valIS)); 661c506a872SMatthew G. Knepley if (!valIS) continue; 662c506a872SMatthew G. Knepley PetscCall(ISGetIndices(valIS, &points)); 663c506a872SMatthew G. Knepley PetscCall(ISGetLocalSize(valIS, &n)); 664c506a872SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) { 665c506a872SMatthew G. Knepley const PetscInt p = points[i]; 666c506a872SMatthew G. Knepley 667c506a872SMatthew G. Knepley if ((p >= sStart) && (p < sEnd)) { 668c506a872SMatthew G. Knepley PetscInt loc, adjSize = PETSC_DETERMINE; 669c506a872SMatthew G. Knepley 670c506a872SMatthew G. Knepley /* Handle leaves: shared with the root point */ 671c506a872SMatthew G. Knepley if (local) PetscCall(PetscFindInt(p, nleaves, local, &loc)); 672c506a872SMatthew G. Knepley else loc = (p >= 0 && p < nleaves) ? p : -1; 673c506a872SMatthew G. Knepley if (loc >= 0) { 674c506a872SMatthew G. Knepley const PetscInt remoteRank = remote[loc].rank; 675c506a872SMatthew G. Knepley 676c506a872SMatthew G. Knepley PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 677c506a872SMatthew G. Knepley for (PetscInt a = 0; a < adjSize; ++a) { 678c506a872SMatthew G. Knepley PetscBool insert = PETSC_TRUE; 679c506a872SMatthew G. Knepley 680c506a872SMatthew G. Knepley for (el = 0; el < numExLabels; ++el) { 681c506a872SMatthew G. Knepley PetscInt exVal; 682c506a872SMatthew G. Knepley PetscCall(DMLabelGetValue(exLabel[el], adj[a], &exVal)); 6839371c9d4SSatish Balay if (exVal == exValue[el]) { 6849371c9d4SSatish Balay insert = PETSC_FALSE; 6859371c9d4SSatish Balay break; 6869371c9d4SSatish Balay } 687c506a872SMatthew G. Knepley } 688c506a872SMatthew G. Knepley if (insert) PetscCall(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 689c506a872SMatthew G. Knepley } 690c506a872SMatthew G. Knepley } 691c506a872SMatthew G. Knepley /* Some leaves share a root with other leaves on different processes */ 6923ba16761SJacob Faibussowitsch PetscCall(HandlePoint_Private(dm, p, leafSection, nrank, numExLabels, exLabel, exValue, ovAdjByRank)); 693c506a872SMatthew G. Knepley } 694c506a872SMatthew G. Knepley /* Roots are shared with leaves */ 6953ba16761SJacob Faibussowitsch PetscCall(HandlePoint_Private(dm, p, rootSection, rrank, numExLabels, exLabel, exValue, ovAdjByRank)); 696c506a872SMatthew G. Knepley } 697c506a872SMatthew G. Knepley PetscCall(ISRestoreIndices(valIS, &points)); 698c506a872SMatthew G. Knepley PetscCall(ISDestroy(&valIS)); 699c506a872SMatthew G. Knepley } 700c506a872SMatthew G. Knepley PetscCall(PetscFree(adj)); 701c506a872SMatthew G. Knepley PetscCall(ISRestoreIndices(rootrank, &rrank)); 702c506a872SMatthew G. Knepley PetscCall(ISRestoreIndices(leafrank, &nrank)); 703c506a872SMatthew G. Knepley /* We require the closure in the overlap */ 704c506a872SMatthew G. Knepley PetscCall(DMPlexPartitionLabelClosure(dm, ovAdjByRank)); 705c506a872SMatthew G. Knepley PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-overlap_view", &flg)); 706c506a872SMatthew G. Knepley if (flg) { 707c506a872SMatthew G. Knepley PetscViewer viewer; 708c506a872SMatthew G. Knepley PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &viewer)); 709c506a872SMatthew G. Knepley PetscCall(DMLabelView(ovAdjByRank, viewer)); 710c506a872SMatthew G. Knepley } 711c506a872SMatthew G. Knepley /* Invert sender to receiver label */ 712c506a872SMatthew G. Knepley PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel)); 713c506a872SMatthew G. Knepley PetscCall(DMPlexPartitionLabelInvert(dm, ovAdjByRank, NULL, *ovLabel)); 714c506a872SMatthew G. Knepley /* Add owned points, except for shared local points */ 715c506a872SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) PetscCall(DMLabelSetValue(*ovLabel, p, rank)); 716c506a872SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 717c506a872SMatthew G. Knepley PetscCall(DMLabelClearValue(*ovLabel, local[l], rank)); 718c506a872SMatthew G. Knepley PetscCall(DMLabelSetValue(*ovLabel, remote[l].index, remote[l].rank)); 719c506a872SMatthew G. Knepley } 720c506a872SMatthew G. Knepley /* Clean up */ 721c506a872SMatthew G. Knepley PetscCall(DMLabelDestroy(&ovAdjByRank)); 7223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 723c506a872SMatthew G. Knepley } 724c506a872SMatthew G. Knepley 72524cc2ca5SMatthew G. Knepley /*@C 72620f4b53cSBarry Smith DMPlexCreateOverlapMigrationSF - Create a `PetscSF` describing the new mesh distribution to make the overlap described by the input `PetscSF` 72724cc2ca5SMatthew G. Knepley 72820f4b53cSBarry Smith Collective 72924cc2ca5SMatthew G. Knepley 73024cc2ca5SMatthew G. Knepley Input Parameters: 73120f4b53cSBarry Smith + dm - The `DM` 73220f4b53cSBarry Smith - overlapSF - The `PetscSF` mapping ghost points in overlap to owner points on other processes 73324cc2ca5SMatthew G. Knepley 734064ec1f3Sprj- Output Parameter: 73520f4b53cSBarry Smith . migrationSF - A `PetscSF` that maps original points in old locations to points in new locations 73624cc2ca5SMatthew G. Knepley 73724cc2ca5SMatthew G. Knepley Level: developer 73824cc2ca5SMatthew G. Knepley 73920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexCreateOverlapLabel()`, `DMPlexDistributeOverlap()`, `DMPlexDistribute()` 74024cc2ca5SMatthew G. Knepley @*/ 741d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateOverlapMigrationSF(DM dm, PetscSF overlapSF, PetscSF *migrationSF) 742d71ae5a4SJacob Faibussowitsch { 74346f9b1c3SMichael Lange MPI_Comm comm; 7449852e123SBarry Smith PetscMPIInt rank, size; 74546f9b1c3SMichael Lange PetscInt d, dim, p, pStart, pEnd, nroots, nleaves, newLeaves, point, numSharedPoints; 74646f9b1c3SMichael Lange PetscInt *pointDepths, *remoteDepths, *ilocal; 74746f9b1c3SMichael Lange PetscInt *depthRecv, *depthShift, *depthIdx; 74846f9b1c3SMichael Lange PetscSFNode *iremote; 74946f9b1c3SMichael Lange PetscSF pointSF; 75046f9b1c3SMichael Lange const PetscInt *sharedLocal; 75146f9b1c3SMichael Lange const PetscSFNode *overlapRemote, *sharedRemote; 75246f9b1c3SMichael Lange 75346f9b1c3SMichael Lange PetscFunctionBegin; 75446f9b1c3SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7559566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 7569566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 7589566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 75946f9b1c3SMichael Lange 76046f9b1c3SMichael Lange /* Before building the migration SF we need to know the new stratum offsets */ 7619566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(overlapSF, &nroots, &nleaves, NULL, &overlapRemote)); 7629566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths)); 76346f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) { 7649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 76546f9b1c3SMichael Lange for (p = pStart; p < pEnd; p++) pointDepths[p] = d; 76646f9b1c3SMichael Lange } 76746f9b1c3SMichael Lange for (p = 0; p < nleaves; p++) remoteDepths[p] = -1; 7689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(overlapSF, MPIU_INT, pointDepths, remoteDepths, MPI_REPLACE)); 7699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(overlapSF, MPIU_INT, pointDepths, remoteDepths, MPI_REPLACE)); 77046f9b1c3SMichael Lange 7712d4ee042Sprj- /* Count received points in each stratum and compute the internal strata shift */ 7729566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim + 1, &depthRecv, dim + 1, &depthShift, dim + 1, &depthIdx)); 77346f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) depthRecv[d] = 0; 77446f9b1c3SMichael Lange for (p = 0; p < nleaves; p++) depthRecv[remoteDepths[p]]++; 77546f9b1c3SMichael Lange depthShift[dim] = 0; 77646f9b1c3SMichael Lange for (d = 0; d < dim; d++) depthShift[d] = depthRecv[dim]; 77746f9b1c3SMichael Lange for (d = 1; d < dim; d++) depthShift[d] += depthRecv[0]; 77846f9b1c3SMichael Lange for (d = dim - 2; d > 0; d--) depthShift[d] += depthRecv[d + 1]; 77946f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) { 7809566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 78146f9b1c3SMichael Lange depthIdx[d] = pStart + depthShift[d]; 78246f9b1c3SMichael Lange } 78346f9b1c3SMichael Lange 78446f9b1c3SMichael Lange /* Form the overlap SF build an SF that describes the full overlap migration SF */ 7859566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 78646f9b1c3SMichael Lange newLeaves = pEnd - pStart + nleaves; 7879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newLeaves, &ilocal)); 7889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newLeaves, &iremote)); 78946f9b1c3SMichael Lange /* First map local points to themselves */ 79046f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) { 7919566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 79246f9b1c3SMichael Lange for (p = pStart; p < pEnd; p++) { 79346f9b1c3SMichael Lange point = p + depthShift[d]; 79446f9b1c3SMichael Lange ilocal[point] = point; 79546f9b1c3SMichael Lange iremote[point].index = p; 79646f9b1c3SMichael Lange iremote[point].rank = rank; 79746f9b1c3SMichael Lange depthIdx[d]++; 79846f9b1c3SMichael Lange } 79946f9b1c3SMichael Lange } 80046f9b1c3SMichael Lange 80146f9b1c3SMichael Lange /* Add in the remote roots for currently shared points */ 8029566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &pointSF)); 8039566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, NULL, &numSharedPoints, &sharedLocal, &sharedRemote)); 80446f9b1c3SMichael Lange for (d = 0; d < dim + 1; d++) { 8059566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 80646f9b1c3SMichael Lange for (p = 0; p < numSharedPoints; p++) { 80746f9b1c3SMichael Lange if (pStart <= sharedLocal[p] && sharedLocal[p] < pEnd) { 80846f9b1c3SMichael Lange point = sharedLocal[p] + depthShift[d]; 80946f9b1c3SMichael Lange iremote[point].index = sharedRemote[p].index; 81046f9b1c3SMichael Lange iremote[point].rank = sharedRemote[p].rank; 81146f9b1c3SMichael Lange } 81246f9b1c3SMichael Lange } 81346f9b1c3SMichael Lange } 81446f9b1c3SMichael Lange 81546f9b1c3SMichael Lange /* Now add the incoming overlap points */ 81646f9b1c3SMichael Lange for (p = 0; p < nleaves; p++) { 81746f9b1c3SMichael Lange point = depthIdx[remoteDepths[p]]; 81846f9b1c3SMichael Lange ilocal[point] = point; 81946f9b1c3SMichael Lange iremote[point].index = overlapRemote[p].index; 82046f9b1c3SMichael Lange iremote[point].rank = overlapRemote[p].rank; 82146f9b1c3SMichael Lange depthIdx[remoteDepths[p]]++; 82246f9b1c3SMichael Lange } 8239566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointDepths, remoteDepths)); 82446f9b1c3SMichael Lange 8259566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, migrationSF)); 8269566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*migrationSF, "Overlap Migration SF")); 8279566063dSJacob Faibussowitsch PetscCall(PetscSFSetFromOptions(*migrationSF)); 8289566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8299566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*migrationSF, pEnd - pStart, newLeaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 83046f9b1c3SMichael Lange 8319566063dSJacob Faibussowitsch PetscCall(PetscFree3(depthRecv, depthShift, depthIdx)); 8323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 83370034214SMatthew G. Knepley } 83470034214SMatthew G. Knepley 835a9f1d5b2SMichael Lange /*@ 836f0e73a3dSToby Isaac DMPlexStratifyMigrationSF - Rearrange the leaves of a migration sf for stratification. 837a9f1d5b2SMichael Lange 838064ec1f3Sprj- Input Parameters: 839a9f1d5b2SMichael Lange + dm - The DM 840a9f1d5b2SMichael Lange - sf - A star forest with non-ordered leaves, usually defining a DM point migration 841a9f1d5b2SMichael Lange 842a9f1d5b2SMichael Lange Output Parameter: 843a9f1d5b2SMichael Lange . migrationSF - A star forest with added leaf indirection that ensures the resulting DM is stratified 844a9f1d5b2SMichael Lange 84520f4b53cSBarry Smith Level: developer 84620f4b53cSBarry Smith 847412e9a14SMatthew G. Knepley Note: 848412e9a14SMatthew G. Knepley This lexicographically sorts by (depth, cellType) 849412e9a14SMatthew G. Knepley 85020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexPartitionLabelCreateSF()`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 851a9f1d5b2SMichael Lange @*/ 852d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratifyMigrationSF(DM dm, PetscSF sf, PetscSF *migrationSF) 853d71ae5a4SJacob Faibussowitsch { 854a9f1d5b2SMichael Lange MPI_Comm comm; 8559852e123SBarry Smith PetscMPIInt rank, size; 856412e9a14SMatthew G. Knepley PetscInt d, ldepth, depth, dim, p, pStart, pEnd, nroots, nleaves; 857412e9a14SMatthew G. Knepley PetscSFNode *pointDepths, *remoteDepths; 858412e9a14SMatthew G. Knepley PetscInt *ilocal; 859a9f1d5b2SMichael Lange PetscInt *depthRecv, *depthShift, *depthIdx; 860412e9a14SMatthew G. Knepley PetscInt *ctRecv, *ctShift, *ctIdx; 861a9f1d5b2SMichael Lange const PetscSFNode *iremote; 862a9f1d5b2SMichael Lange 863a9f1d5b2SMichael Lange PetscFunctionBegin; 864a9f1d5b2SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8659566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 8669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 8679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 8689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &ldepth)); 8699566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8701c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&ldepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 87163a3b9bcSJacob Faibussowitsch PetscCheck(!(ldepth >= 0) || !(depth != ldepth), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %" PetscInt_FMT " != %" PetscInt_FMT, ldepth, depth); 8729566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartStratSF, dm, 0, 0, 0)); 873a9f1d5b2SMichael Lange 874a9f1d5b2SMichael Lange /* Before building the migration SF we need to know the new stratum offsets */ 8759566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, &iremote)); 8769566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths)); 8777fab53ddSMatthew G. Knepley for (d = 0; d < depth + 1; ++d) { 8789566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 879f0e73a3dSToby Isaac for (p = pStart; p < pEnd; ++p) { 880412e9a14SMatthew G. Knepley DMPolytopeType ct; 881f0e73a3dSToby Isaac 8829566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 883412e9a14SMatthew G. Knepley pointDepths[p].index = d; 884412e9a14SMatthew G. Knepley pointDepths[p].rank = ct; 885f0e73a3dSToby Isaac } 886412e9a14SMatthew G. Knepley } 8879371c9d4SSatish Balay for (p = 0; p < nleaves; ++p) { 8889371c9d4SSatish Balay remoteDepths[p].index = -1; 8899371c9d4SSatish Balay remoteDepths[p].rank = -1; 8909371c9d4SSatish Balay } 8919566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_2INT, pointDepths, remoteDepths, MPI_REPLACE)); 8929566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_2INT, pointDepths, remoteDepths, MPI_REPLACE)); 893412e9a14SMatthew G. Knepley /* Count received points in each stratum and compute the internal strata shift */ 8949566063dSJacob Faibussowitsch PetscCall(PetscCalloc6(depth + 1, &depthRecv, depth + 1, &depthShift, depth + 1, &depthIdx, DM_NUM_POLYTOPES, &ctRecv, DM_NUM_POLYTOPES, &ctShift, DM_NUM_POLYTOPES, &ctIdx)); 895412e9a14SMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 896412e9a14SMatthew G. Knepley if (remoteDepths[p].rank < 0) { 897412e9a14SMatthew G. Knepley ++depthRecv[remoteDepths[p].index]; 898412e9a14SMatthew G. Knepley } else { 899412e9a14SMatthew G. Knepley ++ctRecv[remoteDepths[p].rank]; 900412e9a14SMatthew G. Knepley } 901412e9a14SMatthew G. Knepley } 902412e9a14SMatthew G. Knepley { 903412e9a14SMatthew G. Knepley PetscInt depths[4], dims[4], shift = 0, i, c; 904412e9a14SMatthew G. Knepley 9058238f61eSMatthew G. Knepley /* Cells (depth), Vertices (0), Faces (depth-1), Edges (1) 9068238f61eSMatthew G. Knepley Consider DM_POLYTOPE_FV_GHOST and DM_POLYTOPE_INTERIOR_GHOST as cells 9078238f61eSMatthew G. Knepley */ 9089371c9d4SSatish Balay depths[0] = depth; 9099371c9d4SSatish Balay depths[1] = 0; 9109371c9d4SSatish Balay depths[2] = depth - 1; 9119371c9d4SSatish Balay depths[3] = 1; 9129371c9d4SSatish Balay dims[0] = dim; 9139371c9d4SSatish Balay dims[1] = 0; 9149371c9d4SSatish Balay dims[2] = dim - 1; 9159371c9d4SSatish Balay dims[3] = 1; 916412e9a14SMatthew G. Knepley for (i = 0; i <= depth; ++i) { 917412e9a14SMatthew G. Knepley const PetscInt dep = depths[i]; 918412e9a14SMatthew G. Knepley const PetscInt dim = dims[i]; 919412e9a14SMatthew G. Knepley 920412e9a14SMatthew G. Knepley for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 9218238f61eSMatthew G. Knepley if (DMPolytopeTypeGetDim((DMPolytopeType)c) != dim && !(i == 0 && (c == DM_POLYTOPE_FV_GHOST || c == DM_POLYTOPE_INTERIOR_GHOST))) continue; 922412e9a14SMatthew G. Knepley ctShift[c] = shift; 923412e9a14SMatthew G. Knepley shift += ctRecv[c]; 924412e9a14SMatthew G. Knepley } 925412e9a14SMatthew G. Knepley depthShift[dep] = shift; 926412e9a14SMatthew G. Knepley shift += depthRecv[dep]; 927412e9a14SMatthew G. Knepley } 928412e9a14SMatthew G. Knepley for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 929412e9a14SMatthew G. Knepley const PetscInt ctDim = DMPolytopeTypeGetDim((DMPolytopeType)c); 930412e9a14SMatthew G. Knepley 9318238f61eSMatthew G. Knepley if ((ctDim < 0 || ctDim > dim) && (c != DM_POLYTOPE_FV_GHOST && c != DM_POLYTOPE_INTERIOR_GHOST)) { 932412e9a14SMatthew G. Knepley ctShift[c] = shift; 933412e9a14SMatthew G. Knepley shift += ctRecv[c]; 934412e9a14SMatthew G. Knepley } 935412e9a14SMatthew G. Knepley } 936412e9a14SMatthew G. Knepley } 937a9f1d5b2SMichael Lange /* Derive a new local permutation based on stratified indices */ 9389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &ilocal)); 9397fab53ddSMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 940412e9a14SMatthew G. Knepley const PetscInt dep = remoteDepths[p].index; 941412e9a14SMatthew G. Knepley const DMPolytopeType ct = (DMPolytopeType)remoteDepths[p].rank; 9427fab53ddSMatthew G. Knepley 943412e9a14SMatthew G. Knepley if ((PetscInt)ct < 0) { 9447fab53ddSMatthew G. Knepley ilocal[p] = depthShift[dep] + depthIdx[dep]; 945412e9a14SMatthew G. Knepley ++depthIdx[dep]; 946412e9a14SMatthew G. Knepley } else { 947412e9a14SMatthew G. Knepley ilocal[p] = ctShift[ct] + ctIdx[ct]; 948412e9a14SMatthew G. Knepley ++ctIdx[ct]; 949412e9a14SMatthew G. Knepley } 950a9f1d5b2SMichael Lange } 9519566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, migrationSF)); 9529566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*migrationSF, "Migration SF")); 9539566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*migrationSF, nroots, nleaves, ilocal, PETSC_OWN_POINTER, (PetscSFNode *)iremote, PETSC_COPY_VALUES)); 9549566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointDepths, remoteDepths)); 9559566063dSJacob Faibussowitsch PetscCall(PetscFree6(depthRecv, depthShift, depthIdx, ctRecv, ctShift, ctIdx)); 9569566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartStratSF, dm, 0, 0, 0)); 9573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 958a9f1d5b2SMichael Lange } 959a9f1d5b2SMichael Lange 96070034214SMatthew G. Knepley /*@ 96120f4b53cSBarry Smith DMPlexDistributeField - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 96270034214SMatthew G. Knepley 96320f4b53cSBarry Smith Collective 96470034214SMatthew G. Knepley 96570034214SMatthew G. Knepley Input Parameters: 96620f4b53cSBarry Smith + dm - The `DMPLEX` object 96720f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 96820f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 969cb15cd0eSMatthew G. Knepley - originalVec - The existing data in a local vector 97070034214SMatthew G. Knepley 97170034214SMatthew G. Knepley Output Parameters: 97220f4b53cSBarry Smith + newSection - The `PetscSF` describing the new data layout 973cb15cd0eSMatthew G. Knepley - newVec - The new data in a local vector 97470034214SMatthew G. Knepley 97570034214SMatthew G. Knepley Level: developer 97670034214SMatthew G. Knepley 97720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeFieldIS()`, `DMPlexDistributeData()` 97870034214SMatthew G. Knepley @*/ 979d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 980d71ae5a4SJacob Faibussowitsch { 98170034214SMatthew G. Knepley PetscSF fieldSF; 98270034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize; 98370034214SMatthew G. Knepley PetscScalar *originalValues, *newValues; 98470034214SMatthew G. Knepley 98570034214SMatthew G. Knepley PetscFunctionBegin; 9869566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeField, dm, 0, 0, 0)); 9879566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 98870034214SMatthew G. Knepley 9899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 9909566063dSJacob Faibussowitsch PetscCall(VecSetSizes(newVec, fieldSize, PETSC_DETERMINE)); 9919566063dSJacob Faibussowitsch PetscCall(VecSetType(newVec, dm->vectype)); 99270034214SMatthew G. Knepley 9939566063dSJacob Faibussowitsch PetscCall(VecGetArray(originalVec, &originalValues)); 9949566063dSJacob Faibussowitsch PetscCall(VecGetArray(newVec, &newValues)); 9959566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 9969566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 9979566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues, MPI_REPLACE)); 9989566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues, MPI_REPLACE)); 9999566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 10009566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(newVec, &newValues)); 10019566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(originalVec, &originalValues)); 10029566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeField, dm, 0, 0, 0)); 10033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100470034214SMatthew G. Knepley } 100570034214SMatthew G. Knepley 100670034214SMatthew G. Knepley /*@ 100720f4b53cSBarry Smith DMPlexDistributeFieldIS - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 100870034214SMatthew G. Knepley 100920f4b53cSBarry Smith Collective 101070034214SMatthew G. Knepley 101170034214SMatthew G. Knepley Input Parameters: 101220f4b53cSBarry Smith + dm - The `DMPLEX` object 101320f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 101420f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 101570034214SMatthew G. Knepley - originalIS - The existing data 101670034214SMatthew G. Knepley 101770034214SMatthew G. Knepley Output Parameters: 101820f4b53cSBarry Smith + newSection - The `PetscSF` describing the new data layout 101970034214SMatthew G. Knepley - newIS - The new data 102070034214SMatthew G. Knepley 102170034214SMatthew G. Knepley Level: developer 102270034214SMatthew G. Knepley 102320f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeField()`, `DMPlexDistributeData()` 102470034214SMatthew G. Knepley @*/ 1025d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeFieldIS(DM dm, PetscSF pointSF, PetscSection originalSection, IS originalIS, PetscSection newSection, IS *newIS) 1026d71ae5a4SJacob Faibussowitsch { 102770034214SMatthew G. Knepley PetscSF fieldSF; 102870034214SMatthew G. Knepley PetscInt *newValues, *remoteOffsets, fieldSize; 102970034214SMatthew G. Knepley const PetscInt *originalValues; 103070034214SMatthew G. Knepley 103170034214SMatthew G. Knepley PetscFunctionBegin; 10329566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeField, dm, 0, 0, 0)); 10339566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 103470034214SMatthew G. Knepley 10359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 10369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(fieldSize, &newValues)); 103770034214SMatthew G. Knepley 10389566063dSJacob Faibussowitsch PetscCall(ISGetIndices(originalIS, &originalValues)); 10399566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 10409566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 10419566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, MPIU_INT, (PetscInt *)originalValues, newValues, MPI_REPLACE)); 10429566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, MPIU_INT, (PetscInt *)originalValues, newValues, MPI_REPLACE)); 10439566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 10449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(originalIS, &originalValues)); 10459566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pointSF), fieldSize, newValues, PETSC_OWN_POINTER, newIS)); 10469566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeField, dm, 0, 0, 0)); 10473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 104870034214SMatthew G. Knepley } 104970034214SMatthew G. Knepley 105070034214SMatthew G. Knepley /*@ 105120f4b53cSBarry Smith DMPlexDistributeData - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 105270034214SMatthew G. Knepley 105320f4b53cSBarry Smith Collective 105470034214SMatthew G. Knepley 105570034214SMatthew G. Knepley Input Parameters: 105620f4b53cSBarry Smith + dm - The `DMPLEX` object 105720f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 105820f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 105970034214SMatthew G. Knepley . datatype - The type of data 106070034214SMatthew G. Knepley - originalData - The existing data 106170034214SMatthew G. Knepley 106270034214SMatthew G. Knepley Output Parameters: 106320f4b53cSBarry Smith + newSection - The `PetscSection` describing the new data layout 106470034214SMatthew G. Knepley - newData - The new data 106570034214SMatthew G. Knepley 106670034214SMatthew G. Knepley Level: developer 106770034214SMatthew G. Knepley 106820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexDistributeField()` 106970034214SMatthew G. Knepley @*/ 1070d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeData(DM dm, PetscSF pointSF, PetscSection originalSection, MPI_Datatype datatype, void *originalData, PetscSection newSection, void **newData) 1071d71ae5a4SJacob Faibussowitsch { 107270034214SMatthew G. Knepley PetscSF fieldSF; 107370034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize; 107470034214SMatthew G. Knepley PetscMPIInt dataSize; 107570034214SMatthew G. Knepley 107670034214SMatthew G. Knepley PetscFunctionBegin; 10779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeData, dm, 0, 0, 0)); 10789566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 107970034214SMatthew G. Knepley 10809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &fieldSize)); 10819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_size(datatype, &dataSize)); 10829566063dSJacob Faibussowitsch PetscCall(PetscMalloc(fieldSize * dataSize, newData)); 108370034214SMatthew G. Knepley 10849566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 10859566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 10869566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(fieldSF, datatype, originalData, *newData, MPI_REPLACE)); 10879566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(fieldSF, datatype, originalData, *newData, MPI_REPLACE)); 10889566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&fieldSF)); 10899566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeData, dm, 0, 0, 0)); 10903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 109170034214SMatthew G. Knepley } 109270034214SMatthew G. Knepley 1093d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeCones(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel) 1094d71ae5a4SJacob Faibussowitsch { 1095cc71bff1SMichael Lange DM_Plex *pmesh = (DM_Plex *)(dmParallel)->data; 1096cc71bff1SMichael Lange MPI_Comm comm; 1097cc71bff1SMichael Lange PetscSF coneSF; 1098cc71bff1SMichael Lange PetscSection originalConeSection, newConeSection; 1099ac04eaf7SToby Isaac PetscInt *remoteOffsets, *cones, *globCones, *newCones, newConesSize; 1100cc71bff1SMichael Lange PetscBool flg; 1101cc71bff1SMichael Lange 1102cc71bff1SMichael Lange PetscFunctionBegin; 1103cc71bff1SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 11040c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5); 11059566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeCones, dm, 0, 0, 0)); 1106cc71bff1SMichael Lange /* Distribute cone section */ 11079566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 11089566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &originalConeSection)); 11099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dmParallel, &newConeSection)); 11109566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(migrationSF, originalConeSection, &remoteOffsets, newConeSection)); 11119566063dSJacob Faibussowitsch PetscCall(DMSetUp(dmParallel)); 1112cc71bff1SMichael Lange /* Communicate and renumber cones */ 11139566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(migrationSF, originalConeSection, remoteOffsets, newConeSection, &coneSF)); 11149566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 11159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 1116ac04eaf7SToby Isaac if (original) { 1117ac04eaf7SToby Isaac PetscInt numCones; 1118ac04eaf7SToby Isaac 11199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(originalConeSection, &numCones)); 11209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCones, &globCones)); 11219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(original, numCones, cones, globCones)); 1122367003a6SStefano Zampini } else { 1123ac04eaf7SToby Isaac globCones = cones; 1124ac04eaf7SToby Isaac } 11259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dmParallel, &newCones)); 11269566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coneSF, MPIU_INT, globCones, newCones, MPI_REPLACE)); 11279566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coneSF, MPIU_INT, globCones, newCones, MPI_REPLACE)); 11281baa6e33SBarry Smith if (original) PetscCall(PetscFree(globCones)); 11299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newConeSection, &newConesSize)); 11309566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones)); 113176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 11323533c52bSMatthew G. Knepley PetscInt p; 11333533c52bSMatthew G. Knepley PetscBool valid = PETSC_TRUE; 11343533c52bSMatthew G. Knepley for (p = 0; p < newConesSize; ++p) { 11359371c9d4SSatish Balay if (newCones[p] < 0) { 11369371c9d4SSatish Balay valid = PETSC_FALSE; 11379371c9d4SSatish Balay PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Point %" PetscInt_FMT " not in overlap SF\n", PetscGlobalRank, p)); 11389371c9d4SSatish Balay } 11393533c52bSMatthew G. Knepley } 114028b400f6SJacob Faibussowitsch PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map"); 11413533c52bSMatthew G. Knepley } 11429566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-cones_view", &flg)); 1143cc71bff1SMichael Lange if (flg) { 11449566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Serial Cone Section:\n")); 11459566063dSJacob Faibussowitsch PetscCall(PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_(comm))); 11469566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Parallel Cone Section:\n")); 11479566063dSJacob Faibussowitsch PetscCall(PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_(comm))); 11489566063dSJacob Faibussowitsch PetscCall(PetscSFView(coneSF, NULL)); 1149cc71bff1SMichael Lange } 11509566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dm, &cones)); 11519566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dmParallel, &newCones)); 11529566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones, MPI_REPLACE)); 11539566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones, MPI_REPLACE)); 11549566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coneSF)); 11559566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeCones, dm, 0, 0, 0)); 1156eaf898f9SPatrick Sanan /* Create supports and stratify DMPlex */ 1157cc71bff1SMichael Lange { 1158cc71bff1SMichael Lange PetscInt pStart, pEnd; 1159cc71bff1SMichael Lange 11609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd)); 11619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(pmesh->supportSection, pStart, pEnd)); 1162cc71bff1SMichael Lange } 11639566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dmParallel)); 11649566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dmParallel)); 11651cf84007SMatthew G. Knepley { 11661cf84007SMatthew G. Knepley PetscBool useCone, useClosure, useAnchors; 11671cf84007SMatthew G. Knepley 11689566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 11699566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dmParallel, useCone, useClosure)); 11709566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors)); 11719566063dSJacob Faibussowitsch PetscCall(DMPlexSetAdjacencyUseAnchors(dmParallel, useAnchors)); 11721cf84007SMatthew G. Knepley } 11733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1174cc71bff1SMichael Lange } 1175cc71bff1SMichael Lange 1176d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeCoordinates(DM dm, PetscSF migrationSF, DM dmParallel) 1177d71ae5a4SJacob Faibussowitsch { 11780df0e737SMichael Lange MPI_Comm comm; 11799318fe57SMatthew G. Knepley DM cdm, cdmParallel; 11800df0e737SMichael Lange PetscSection originalCoordSection, newCoordSection; 11810df0e737SMichael Lange Vec originalCoordinates, newCoordinates; 11820df0e737SMichael Lange PetscInt bs; 11830df0e737SMichael Lange const char *name; 11844fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 11850df0e737SMichael Lange 11860df0e737SMichael Lange PetscFunctionBegin; 11870df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 11880c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3); 11890df0e737SMichael Lange 11909566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 11916858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 11926858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dmParallel, &cdmParallel)); 11936858538eSMatthew G. Knepley PetscCall(DMCopyDisc(cdm, cdmParallel)); 11949566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &originalCoordSection)); 11959566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dmParallel, &newCoordSection)); 11969566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &originalCoordinates)); 11970df0e737SMichael Lange if (originalCoordinates) { 11989566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates)); 11999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalCoordinates, &name)); 12009566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)newCoordinates, name)); 12010df0e737SMichael Lange 12029566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates)); 12039566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmParallel, newCoordinates)); 12049566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(originalCoordinates, &bs)); 12059566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(newCoordinates, bs)); 12069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&newCoordinates)); 12070df0e737SMichael Lange } 12086858538eSMatthew G. Knepley 12096858538eSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12104fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L)); 12114fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmParallel, maxCell, Lstart, L)); 12126858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdm)); 12136858538eSMatthew G. Knepley if (cdm) { 12146858538eSMatthew G. Knepley PetscCall(DMClone(dmParallel, &cdmParallel)); 12156858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmParallel, cdmParallel)); 12169566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(cdm, cdmParallel)); 12176858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmParallel)); 12186858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &originalCoordSection)); 12196858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &originalCoordinates)); 12206858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(comm, &newCoordSection)); 12216858538eSMatthew G. Knepley if (originalCoordinates) { 12226858538eSMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates)); 12236858538eSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)originalCoordinates, &name)); 12246858538eSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)newCoordinates, name)); 12256858538eSMatthew G. Knepley 12266858538eSMatthew G. Knepley PetscCall(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates)); 12276858538eSMatthew G. Knepley PetscCall(VecGetBlockSize(originalCoordinates, &bs)); 12286858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(newCoordinates, bs)); 12296858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(dmParallel, bs, newCoordSection)); 12306858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmParallel, newCoordinates)); 12316858538eSMatthew G. Knepley PetscCall(VecDestroy(&newCoordinates)); 12326858538eSMatthew G. Knepley } 12336858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&newCoordSection)); 12346858538eSMatthew G. Knepley } 12353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12360df0e737SMichael Lange } 12370df0e737SMichael Lange 1238d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeLabels(DM dm, PetscSF migrationSF, DM dmParallel) 1239d71ae5a4SJacob Faibussowitsch { 1240df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 12410df0e737SMichael Lange MPI_Comm comm; 12427980c9d4SMatthew G. Knepley DMLabel depthLabel; 12430df0e737SMichael Lange PetscMPIInt rank; 12447980c9d4SMatthew G. Knepley PetscInt depth, d, numLabels, numLocalLabels, l; 1245df0420ecSMatthew G. Knepley PetscBool hasLabels = PETSC_FALSE, lsendDepth, sendDepth; 1246df0420ecSMatthew G. Knepley PetscObjectState depthState = -1; 12470df0e737SMichael Lange 12480df0e737SMichael Lange PetscFunctionBegin; 12490df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 12500c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3); 12510c86c063SLisandro Dalcin 12529566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeLabels, dm, 0, 0, 0)); 12539566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 12550df0e737SMichael Lange 1256df0420ecSMatthew G. Knepley /* If the user has changed the depth label, communicate it instead */ 12579566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 12589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 12599566063dSJacob Faibussowitsch if (depthLabel) PetscCall(PetscObjectStateGet((PetscObject)depthLabel, &depthState)); 1260df0420ecSMatthew G. Knepley lsendDepth = mesh->depthState != depthState ? PETSC_TRUE : PETSC_FALSE; 12611c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lsendDepth, &sendDepth, 1, MPIU_BOOL, MPI_LOR, comm)); 1262df0420ecSMatthew G. Knepley if (sendDepth) { 12639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dmParallel, &dmParallel->depthLabel)); 12649566063dSJacob Faibussowitsch PetscCall(DMRemoveLabelBySelf(dmParallel, &dmParallel->depthLabel, PETSC_FALSE)); 1265df0420ecSMatthew G. Knepley } 1266d995df53SMatthew G. Knepley /* Everyone must have either the same number of labels, or none */ 12679566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLocalLabels)); 1268d995df53SMatthew G. Knepley numLabels = numLocalLabels; 12699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm)); 1270627847f0SMatthew G. Knepley if (numLabels == numLocalLabels) hasLabels = PETSC_TRUE; 12715d80c0bfSVaclav Hapla for (l = 0; l < numLabels; ++l) { 1272bdd2d751SMichael Lange DMLabel label = NULL, labelNew = NULL; 127383e10cb3SLisandro Dalcin PetscBool isDepth, lisOutput = PETSC_TRUE, isOutput; 1274d67d17b1SMatthew G. Knepley const char *name = NULL; 12750df0e737SMichael Lange 1276d67d17b1SMatthew G. Knepley if (hasLabels) { 12779566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(dm, l, &label)); 12780df0e737SMichael Lange /* Skip "depth" because it is recreated */ 12799566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)label, &name)); 12809566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 1281bbcf679cSJacob Faibussowitsch } else { 1282bbcf679cSJacob Faibussowitsch isDepth = PETSC_FALSE; 1283d67d17b1SMatthew G. Knepley } 12849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&isDepth, 1, MPIU_BOOL, 0, comm)); 128583e10cb3SLisandro Dalcin if (isDepth && !sendDepth) continue; 12869566063dSJacob Faibussowitsch PetscCall(DMLabelDistribute(label, migrationSF, &labelNew)); 128783e10cb3SLisandro Dalcin if (isDepth) { 12887980c9d4SMatthew G. Knepley /* Put in any missing strata which can occur if users are managing the depth label themselves */ 12897980c9d4SMatthew G. Knepley PetscInt gdepth; 12907980c9d4SMatthew G. Knepley 12911c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&depth, &gdepth, 1, MPIU_INT, MPI_MAX, comm)); 129263a3b9bcSJacob Faibussowitsch PetscCheck(!(depth >= 0) || !(gdepth != depth), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %" PetscInt_FMT " != %" PetscInt_FMT, depth, gdepth); 12937980c9d4SMatthew G. Knepley for (d = 0; d <= gdepth; ++d) { 12947980c9d4SMatthew G. Knepley PetscBool has; 12957980c9d4SMatthew G. Knepley 12969566063dSJacob Faibussowitsch PetscCall(DMLabelHasStratum(labelNew, d, &has)); 12979566063dSJacob Faibussowitsch if (!has) PetscCall(DMLabelAddStratum(labelNew, d)); 12987980c9d4SMatthew G. Knepley } 12997980c9d4SMatthew G. Knepley } 13009566063dSJacob Faibussowitsch PetscCall(DMAddLabel(dmParallel, labelNew)); 130183e10cb3SLisandro Dalcin /* Put the output flag in the new label */ 13029566063dSJacob Faibussowitsch if (hasLabels) PetscCall(DMGetLabelOutput(dm, name, &lisOutput)); 13031c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lisOutput, &isOutput, 1, MPIU_BOOL, MPI_LAND, comm)); 13049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)labelNew, &name)); 13059566063dSJacob Faibussowitsch PetscCall(DMSetLabelOutput(dmParallel, name, isOutput)); 13069566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&labelNew)); 13070df0e737SMichael Lange } 1308695799ffSMatthew G. Knepley { 1309695799ffSMatthew G. Knepley DMLabel ctLabel; 1310695799ffSMatthew G. Knepley 1311695799ffSMatthew G. Knepley // Reset label for fast lookup 1312695799ffSMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dmParallel, &ctLabel)); 1313695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 1314695799ffSMatthew G. Knepley } 13159566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeLabels, dm, 0, 0, 0)); 13163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13170df0e737SMichael Lange } 13180df0e737SMichael Lange 1319d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDistributeSetupTree(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel) 1320d71ae5a4SJacob Faibussowitsch { 132115078cd4SMichael Lange DM_Plex *mesh = (DM_Plex *)dm->data; 132215078cd4SMichael Lange DM_Plex *pmesh = (DM_Plex *)(dmParallel)->data; 1323a6f36705SMichael Lange MPI_Comm comm; 1324a6f36705SMichael Lange DM refTree; 1325a6f36705SMichael Lange PetscSection origParentSection, newParentSection; 1326a6f36705SMichael Lange PetscInt *origParents, *origChildIDs; 1327a6f36705SMichael Lange PetscBool flg; 1328a6f36705SMichael Lange 1329a6f36705SMichael Lange PetscFunctionBegin; 1330a6f36705SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13310c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5); 13329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 1333a6f36705SMichael Lange 1334a6f36705SMichael Lange /* Set up tree */ 13359566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 13369566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(dmParallel, refTree)); 13379566063dSJacob Faibussowitsch PetscCall(DMPlexGetTree(dm, &origParentSection, &origParents, &origChildIDs, NULL, NULL)); 1338a6f36705SMichael Lange if (origParentSection) { 1339a6f36705SMichael Lange PetscInt pStart, pEnd; 134008633170SToby Isaac PetscInt *newParents, *newChildIDs, *globParents; 1341a6f36705SMichael Lange PetscInt *remoteOffsetsParents, newParentSize; 1342a6f36705SMichael Lange PetscSF parentSF; 1343a6f36705SMichael Lange 13449566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmParallel, &pStart, &pEnd)); 13459566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmParallel), &newParentSection)); 13469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newParentSection, pStart, pEnd)); 13479566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(migrationSF, origParentSection, &remoteOffsetsParents, newParentSection)); 13489566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(migrationSF, origParentSection, remoteOffsetsParents, newParentSection, &parentSF)); 13499566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsParents)); 13509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newParentSection, &newParentSize)); 13519566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(newParentSize, &newParents, newParentSize, &newChildIDs)); 135208633170SToby Isaac if (original) { 135308633170SToby Isaac PetscInt numParents; 135408633170SToby Isaac 13559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(origParentSection, &numParents)); 13569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numParents, &globParents)); 13579566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(original, numParents, origParents, globParents)); 13589371c9d4SSatish Balay } else { 135908633170SToby Isaac globParents = origParents; 136008633170SToby Isaac } 13619566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(parentSF, MPIU_INT, globParents, newParents, MPI_REPLACE)); 13629566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(parentSF, MPIU_INT, globParents, newParents, MPI_REPLACE)); 13631baa6e33SBarry Smith if (original) PetscCall(PetscFree(globParents)); 13649566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(parentSF, MPIU_INT, origChildIDs, newChildIDs, MPI_REPLACE)); 13659566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(parentSF, MPIU_INT, origChildIDs, newChildIDs, MPI_REPLACE)); 13669566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newParentSize, newParents, NULL, newParents)); 136776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 13684a54e071SToby Isaac PetscInt p; 13694a54e071SToby Isaac PetscBool valid = PETSC_TRUE; 13704a54e071SToby Isaac for (p = 0; p < newParentSize; ++p) { 13719371c9d4SSatish Balay if (newParents[p] < 0) { 13729371c9d4SSatish Balay valid = PETSC_FALSE; 13739371c9d4SSatish Balay PetscCall(PetscPrintf(PETSC_COMM_SELF, "Point %" PetscInt_FMT " not in overlap SF\n", p)); 13749371c9d4SSatish Balay } 13754a54e071SToby Isaac } 137628b400f6SJacob Faibussowitsch PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map"); 13774a54e071SToby Isaac } 13789566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-parents_view", &flg)); 1379a6f36705SMichael Lange if (flg) { 13809566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Serial Parent Section: \n")); 13819566063dSJacob Faibussowitsch PetscCall(PetscSectionView(origParentSection, PETSC_VIEWER_STDOUT_(comm))); 13829566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Parallel Parent Section: \n")); 13839566063dSJacob Faibussowitsch PetscCall(PetscSectionView(newParentSection, PETSC_VIEWER_STDOUT_(comm))); 13849566063dSJacob Faibussowitsch PetscCall(PetscSFView(parentSF, NULL)); 1385a6f36705SMichael Lange } 13869566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(dmParallel, newParentSection, newParents, newChildIDs)); 13879566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newParentSection)); 13889566063dSJacob Faibussowitsch PetscCall(PetscFree2(newParents, newChildIDs)); 13899566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&parentSF)); 1390a6f36705SMichael Lange } 139115078cd4SMichael Lange pmesh->useAnchors = mesh->useAnchors; 13923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1393a6f36705SMichael Lange } 13940df0e737SMichael Lange 139598ba2d7fSLawrence Mitchell /*@ 139620f4b53cSBarry Smith DMPlexSetPartitionBalance - Should distribution of the `DM` attempt to balance the shared point partition? 139798ba2d7fSLawrence Mitchell 139898ba2d7fSLawrence Mitchell Input Parameters: 139920f4b53cSBarry Smith + dm - The `DMPLEX` object 140098ba2d7fSLawrence Mitchell - flg - Balance the partition? 140198ba2d7fSLawrence Mitchell 140298ba2d7fSLawrence Mitchell Level: intermediate 140398ba2d7fSLawrence Mitchell 140420f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetPartitionBalance()` 140598ba2d7fSLawrence Mitchell @*/ 1406d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetPartitionBalance(DM dm, PetscBool flg) 1407d71ae5a4SJacob Faibussowitsch { 140898ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 140998ba2d7fSLawrence Mitchell 141098ba2d7fSLawrence Mitchell PetscFunctionBegin; 141198ba2d7fSLawrence Mitchell mesh->partitionBalance = flg; 14123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 141398ba2d7fSLawrence Mitchell } 141498ba2d7fSLawrence Mitchell 141598ba2d7fSLawrence Mitchell /*@ 141620f4b53cSBarry Smith DMPlexGetPartitionBalance - Does distribution of the `DM` attempt to balance the shared point partition? 141798ba2d7fSLawrence Mitchell 141898ba2d7fSLawrence Mitchell Input Parameter: 141920f4b53cSBarry Smith . dm - The `DMPLEX` object 142098ba2d7fSLawrence Mitchell 142198ba2d7fSLawrence Mitchell Output Parameter: 1422a2b725a8SWilliam Gropp . flg - Balance the partition? 142398ba2d7fSLawrence Mitchell 142498ba2d7fSLawrence Mitchell Level: intermediate 142598ba2d7fSLawrence Mitchell 142620f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexSetPartitionBalance()` 142798ba2d7fSLawrence Mitchell @*/ 1428d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPartitionBalance(DM dm, PetscBool *flg) 1429d71ae5a4SJacob Faibussowitsch { 143098ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 143198ba2d7fSLawrence Mitchell 143298ba2d7fSLawrence Mitchell PetscFunctionBegin; 143398ba2d7fSLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14344f572ea9SToby Isaac PetscAssertPointer(flg, 2); 143598ba2d7fSLawrence Mitchell *flg = mesh->partitionBalance; 14363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 143798ba2d7fSLawrence Mitchell } 143898ba2d7fSLawrence Mitchell 1439fc02256fSLawrence Mitchell typedef struct { 1440fc02256fSLawrence Mitchell PetscInt vote, rank, index; 1441fc02256fSLawrence Mitchell } Petsc3Int; 1442fc02256fSLawrence Mitchell 1443fc02256fSLawrence Mitchell /* MaxLoc, but carry a third piece of information around */ 1444d71ae5a4SJacob Faibussowitsch static void MPIAPI MaxLocCarry(void *in_, void *inout_, PetscMPIInt *len_, MPI_Datatype *dtype) 1445d71ae5a4SJacob Faibussowitsch { 1446fc02256fSLawrence Mitchell Petsc3Int *a = (Petsc3Int *)inout_; 1447fc02256fSLawrence Mitchell Petsc3Int *b = (Petsc3Int *)in_; 1448fc02256fSLawrence Mitchell PetscInt i, len = *len_; 1449fc02256fSLawrence Mitchell for (i = 0; i < len; i++) { 1450fc02256fSLawrence Mitchell if (a[i].vote < b[i].vote) { 1451fc02256fSLawrence Mitchell a[i].vote = b[i].vote; 1452fc02256fSLawrence Mitchell a[i].rank = b[i].rank; 1453fc02256fSLawrence Mitchell a[i].index = b[i].index; 1454fc02256fSLawrence Mitchell } else if (a[i].vote <= b[i].vote) { 1455fc02256fSLawrence Mitchell if (a[i].rank >= b[i].rank) { 1456fc02256fSLawrence Mitchell a[i].rank = b[i].rank; 1457fc02256fSLawrence Mitchell a[i].index = b[i].index; 1458fc02256fSLawrence Mitchell } 1459fc02256fSLawrence Mitchell } 1460fc02256fSLawrence Mitchell } 1461fc02256fSLawrence Mitchell } 1462fc02256fSLawrence Mitchell 1463f5bf2dbfSMichael Lange /*@C 146420f4b53cSBarry Smith DMPlexCreatePointSF - Build a point `PetscSF` from an `PetscSF` describing a point migration 1465f5bf2dbfSMichael Lange 1466064ec1f3Sprj- Input Parameters: 146720f4b53cSBarry Smith + dm - The source `DMPLEX` object 1468f5bf2dbfSMichael Lange . migrationSF - The star forest that describes the parallel point remapping 1469d8d19677SJose E. Roman - ownership - Flag causing a vote to determine point ownership 1470f5bf2dbfSMichael Lange 1471f5bf2dbfSMichael Lange Output Parameter: 147220f4b53cSBarry Smith . pointSF - The star forest describing the point overlap in the remapped `DM` 14733618482eSVaclav Hapla 1474f5bf2dbfSMichael Lange Level: developer 1475f5bf2dbfSMichael Lange 147620f4b53cSBarry Smith Note: 147720f4b53cSBarry Smith Output `pointSF` is guaranteed to have the array of local indices (leaves) sorted. 147820f4b53cSBarry Smith 147920f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 1480f5bf2dbfSMichael Lange @*/ 1481d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointSF(DM dm, PetscSF migrationSF, PetscBool ownership, PetscSF *pointSF) 1482d71ae5a4SJacob Faibussowitsch { 148323193802SMatthew G. Knepley PetscMPIInt rank, size; 14841627f6ccSMichael Lange PetscInt p, nroots, nleaves, idx, npointLeaves; 1485f5bf2dbfSMichael Lange PetscInt *pointLocal; 1486f5bf2dbfSMichael Lange const PetscInt *leaves; 1487f5bf2dbfSMichael Lange const PetscSFNode *roots; 1488f5bf2dbfSMichael Lange PetscSFNode *rootNodes, *leafNodes, *pointRemote; 148923193802SMatthew G. Knepley Vec shifts; 1490cae3e4f3SLawrence Mitchell const PetscInt numShifts = 13759; 149123193802SMatthew G. Knepley const PetscScalar *shift = NULL; 149223193802SMatthew G. Knepley const PetscBool shiftDebug = PETSC_FALSE; 149398ba2d7fSLawrence Mitchell PetscBool balance; 1494f5bf2dbfSMichael Lange 1495f5bf2dbfSMichael Lange PetscFunctionBegin; 1496f5bf2dbfSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 14989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 14999566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreatePointSF, dm, 0, 0, 0)); 1500f5bf2dbfSMichael Lange 15019566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitionBalance(dm, &balance)); 15029566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(migrationSF, &nroots, &nleaves, &leaves, &roots)); 15039566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nroots, &rootNodes, nleaves, &leafNodes)); 1504f5bf2dbfSMichael Lange if (ownership) { 1505fc02256fSLawrence Mitchell MPI_Op op; 1506fc02256fSLawrence Mitchell MPI_Datatype datatype; 1507fc02256fSLawrence Mitchell Petsc3Int *rootVote = NULL, *leafVote = NULL; 150823193802SMatthew 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. */ 150998ba2d7fSLawrence Mitchell if (balance) { 151023193802SMatthew G. Knepley PetscRandom r; 151123193802SMatthew G. Knepley 15129566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_SELF, &r)); 15139566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(r, 0, 2467 * size)); 15149566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &shifts)); 15159566063dSJacob Faibussowitsch PetscCall(VecSetSizes(shifts, numShifts, numShifts)); 15169566063dSJacob Faibussowitsch PetscCall(VecSetType(shifts, VECSTANDARD)); 15179566063dSJacob Faibussowitsch PetscCall(VecSetRandom(shifts, r)); 15189566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&r)); 15199566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(shifts, &shift)); 152023193802SMatthew G. Knepley } 152123193802SMatthew G. Knepley 15229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nroots, &rootVote)); 15239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &leafVote)); 152423193802SMatthew G. Knepley /* Point ownership vote: Process with highest rank owns shared points */ 1525f5bf2dbfSMichael Lange for (p = 0; p < nleaves; ++p) { 152623193802SMatthew G. Knepley if (shiftDebug) { 15279371c9d4SSatish 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, 15289371c9d4SSatish Balay (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]), (rank + (shift ? (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]) : 0)) % size)); 152923193802SMatthew G. Knepley } 1530f5bf2dbfSMichael Lange /* Either put in a bid or we know we own it */ 1531fc02256fSLawrence Mitchell leafVote[p].vote = (rank + (shift ? (PetscInt)PetscRealPart(shift[roots[p].index % numShifts]) : 0)) % size; 1532fc02256fSLawrence Mitchell leafVote[p].rank = rank; 1533fc02256fSLawrence Mitchell leafVote[p].index = p; 1534f5bf2dbfSMichael Lange } 1535f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) { 15361627f6ccSMichael Lange /* Root must not participate in the reduction, flag so that MAXLOC does not use */ 1537fc02256fSLawrence Mitchell rootVote[p].vote = -3; 1538fc02256fSLawrence Mitchell rootVote[p].rank = -3; 1539fc02256fSLawrence Mitchell rootVote[p].index = -3; 1540f5bf2dbfSMichael Lange } 15419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(3, MPIU_INT, &datatype)); 15429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&datatype)); 15439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(&MaxLocCarry, 1, &op)); 15449566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(migrationSF, datatype, leafVote, rootVote, op)); 15459566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(migrationSF, datatype, leafVote, rootVote, op)); 15469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&op)); 15479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&datatype)); 1548c091126eSLawrence Mitchell for (p = 0; p < nroots; p++) { 1549fc02256fSLawrence Mitchell rootNodes[p].rank = rootVote[p].rank; 1550fc02256fSLawrence Mitchell rootNodes[p].index = rootVote[p].index; 1551c091126eSLawrence Mitchell } 15529566063dSJacob Faibussowitsch PetscCall(PetscFree(leafVote)); 15539566063dSJacob Faibussowitsch PetscCall(PetscFree(rootVote)); 1554f5bf2dbfSMichael Lange } else { 1555f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) { 1556f5bf2dbfSMichael Lange rootNodes[p].index = -1; 1557f5bf2dbfSMichael Lange rootNodes[p].rank = rank; 1558fc02256fSLawrence Mitchell } 1559f5bf2dbfSMichael Lange for (p = 0; p < nleaves; p++) { 1560f5bf2dbfSMichael Lange /* Write new local id into old location */ 1561ad540459SPierre Jolivet if (roots[p].rank == rank) rootNodes[roots[p].index].index = leaves ? leaves[p] : p; 1562f5bf2dbfSMichael Lange } 1563f5bf2dbfSMichael Lange } 15649566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(migrationSF, MPIU_2INT, rootNodes, leafNodes, MPI_REPLACE)); 15659566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(migrationSF, MPIU_2INT, rootNodes, leafNodes, MPI_REPLACE)); 1566f5bf2dbfSMichael Lange 156723193802SMatthew G. Knepley for (npointLeaves = 0, p = 0; p < nleaves; p++) { 1568b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) npointLeaves++; 156923193802SMatthew G. Knepley } 15709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npointLeaves, &pointLocal)); 15719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npointLeaves, &pointRemote)); 1572f5bf2dbfSMichael Lange for (idx = 0, p = 0; p < nleaves; p++) { 1573b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) { 15743618482eSVaclav Hapla /* Note that pointLocal is automatically sorted as it is sublist of 0, ..., nleaves-1 */ 1575f5bf2dbfSMichael Lange pointLocal[idx] = p; 1576f5bf2dbfSMichael Lange pointRemote[idx] = leafNodes[p]; 1577f5bf2dbfSMichael Lange idx++; 1578f5bf2dbfSMichael Lange } 1579f5bf2dbfSMichael Lange } 158023193802SMatthew G. Knepley if (shift) { 15819566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(shifts, &shift)); 15829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shifts)); 158323193802SMatthew G. Knepley } 15849566063dSJacob Faibussowitsch if (shiftDebug) PetscCall(PetscSynchronizedFlush(PetscObjectComm((PetscObject)dm), PETSC_STDOUT)); 15859566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), pointSF)); 15869566063dSJacob Faibussowitsch PetscCall(PetscSFSetFromOptions(*pointSF)); 15879566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*pointSF, nleaves, npointLeaves, pointLocal, PETSC_OWN_POINTER, pointRemote, PETSC_OWN_POINTER)); 15889566063dSJacob Faibussowitsch PetscCall(PetscFree2(rootNodes, leafNodes)); 15899566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreatePointSF, dm, 0, 0, 0)); 1590d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, *pointSF, PETSC_FALSE)); 15913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1592f5bf2dbfSMichael Lange } 1593f5bf2dbfSMichael Lange 159415078cd4SMichael Lange /*@C 159520f4b53cSBarry Smith DMPlexMigrate - Migrates internal `DM` data over the supplied star forest 159615078cd4SMichael Lange 159720f4b53cSBarry Smith Collective 159883655b49SVáclav Hapla 1599064ec1f3Sprj- Input Parameters: 160020f4b53cSBarry Smith + dm - The source `DMPLEX` object 1601d8d19677SJose E. Roman - sf - The star forest communication context describing the migration pattern 160215078cd4SMichael Lange 160315078cd4SMichael Lange Output Parameter: 160420f4b53cSBarry Smith . targetDM - The target `DMPLEX` object 160515078cd4SMichael Lange 1606b9f40539SMichael Lange Level: intermediate 160715078cd4SMichael Lange 160820f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()` 160915078cd4SMichael Lange @*/ 1610d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMigrate(DM dm, PetscSF sf, DM targetDM) 1611d71ae5a4SJacob Faibussowitsch { 1612b9f40539SMichael Lange MPI_Comm comm; 1613cc1750acSStefano Zampini PetscInt dim, cdim, nroots; 1614b9f40539SMichael Lange PetscSF sfPoint; 161515078cd4SMichael Lange ISLocalToGlobalMapping ltogMigration; 1616ac04eaf7SToby Isaac ISLocalToGlobalMapping ltogOriginal = NULL; 161715078cd4SMichael Lange 161815078cd4SMichael Lange PetscFunctionBegin; 161915078cd4SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 16209566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Migrate, dm, 0, 0, 0)); 16219566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 16229566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 16239566063dSJacob Faibussowitsch PetscCall(DMSetDimension(targetDM, dim)); 16249566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 16259566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(targetDM, cdim)); 162615078cd4SMichael Lange 1627bfb0467fSMichael Lange /* Check for a one-to-all distribution pattern */ 16289566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 16299566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 1630bfb0467fSMichael Lange if (nroots >= 0) { 1631b9f40539SMichael Lange IS isOriginal; 1632ac04eaf7SToby Isaac PetscInt n, size, nleaves; 1633ac04eaf7SToby Isaac PetscInt *numbering_orig, *numbering_new; 1634367003a6SStefano Zampini 1635b9f40539SMichael Lange /* Get the original point numbering */ 16369566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &isOriginal)); 16379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(isOriginal, <ogOriginal)); 16389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(ltogOriginal, &size)); 16399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltogOriginal, (const PetscInt **)&numbering_orig)); 1640b9f40539SMichael Lange /* Convert to positive global numbers */ 16419371c9d4SSatish Balay for (n = 0; n < size; n++) { 16429371c9d4SSatish Balay if (numbering_orig[n] < 0) numbering_orig[n] = -(numbering_orig[n] + 1); 16439371c9d4SSatish Balay } 1644b9f40539SMichael Lange /* Derive the new local-to-global mapping from the old one */ 16459566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, NULL, NULL)); 16469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &numbering_new)); 16479566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, numbering_orig, numbering_new, MPI_REPLACE)); 16489566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, numbering_orig, numbering_new, MPI_REPLACE)); 16499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, nleaves, numbering_new, PETSC_OWN_POINTER, <ogMigration)); 16509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogOriginal, (const PetscInt **)&numbering_orig)); 16519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isOriginal)); 165215078cd4SMichael Lange } else { 1653bfb0467fSMichael Lange /* One-to-all distribution pattern: We can derive LToG from SF */ 16549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateSF(sf, 0, <ogMigration)); 165515078cd4SMichael Lange } 1656a5a902f7SVaclav Hapla PetscCall(PetscObjectSetName((PetscObject)ltogMigration, "Point renumbering for DM migration")); 1657a5a902f7SVaclav Hapla PetscCall(ISLocalToGlobalMappingViewFromOptions(ltogMigration, (PetscObject)dm, "-partition_view")); 165815078cd4SMichael Lange /* Migrate DM data to target DM */ 16599566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeCones(dm, sf, ltogOriginal, ltogMigration, targetDM)); 16609566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeLabels(dm, sf, targetDM)); 16619566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeCoordinates(dm, sf, targetDM)); 16629566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetupTree(dm, sf, ltogOriginal, ltogMigration, targetDM)); 16639566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<ogOriginal)); 16649566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<ogMigration)); 16659566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Migrate, dm, 0, 0, 0)); 16663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 166715078cd4SMichael Lange } 166815078cd4SMichael Lange 1669*00a1aa47SMatthew G. Knepley /*@ 1670*00a1aa47SMatthew G. Knepley DMPlexRemapMigrationSF - Rewrite the distribution SF to account for overlap 1671*00a1aa47SMatthew G. Knepley 1672*00a1aa47SMatthew G. Knepley Collective 1673*00a1aa47SMatthew G. Knepley 1674*00a1aa47SMatthew G. Knepley Input Parameters: 1675*00a1aa47SMatthew G. Knepley + sfOverlap - The `PetscSF` object just for the overlap 1676*00a1aa47SMatthew G. Knepley - sfMigration - The original distribution `PetscSF` object 1677*00a1aa47SMatthew G. Knepley 1678*00a1aa47SMatthew G. Knepley Output Parameters: 1679*00a1aa47SMatthew G. Knepley . sfMigrationNew - A rewritten `PetscSF` object that incorporates the overlap 1680*00a1aa47SMatthew G. Knepley 1681*00a1aa47SMatthew G. Knepley Level: developer 1682*00a1aa47SMatthew G. Knepley 1683*00a1aa47SMatthew G. Knepley .seealso: `DMPLEX`, `DM`, `DMPlexDistribute()`, `DMPlexDistributeOverlap()`, `DMPlexGetOverlap()` 1684*00a1aa47SMatthew G. Knepley @*/ 1685*00a1aa47SMatthew G. Knepley PetscErrorCode DMPlexRemapMigrationSF(PetscSF sfOverlap, PetscSF sfMigration, PetscSF *sfMigrationNew) 1686*00a1aa47SMatthew G. Knepley { 1687*00a1aa47SMatthew G. Knepley PetscSFNode *newRemote, *permRemote; 1688*00a1aa47SMatthew G. Knepley const PetscInt *oldLeaves; 1689*00a1aa47SMatthew G. Knepley const PetscSFNode *oldRemote; 1690*00a1aa47SMatthew G. Knepley PetscInt nroots, nleaves, noldleaves; 1691*00a1aa47SMatthew G. Knepley 1692*00a1aa47SMatthew G. Knepley PetscFunctionBegin; 1693*00a1aa47SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfMigration, &nroots, &noldleaves, &oldLeaves, &oldRemote)); 1694*00a1aa47SMatthew G. Knepley PetscCall(PetscSFGetGraph(sfOverlap, NULL, &nleaves, NULL, NULL)); 1695*00a1aa47SMatthew G. Knepley PetscCall(PetscMalloc1(nleaves, &newRemote)); 1696*00a1aa47SMatthew G. Knepley /* oldRemote: original root point mapping to original leaf point 1697*00a1aa47SMatthew G. Knepley newRemote: original leaf point mapping to overlapped leaf point */ 1698*00a1aa47SMatthew G. Knepley if (oldLeaves) { 1699*00a1aa47SMatthew G. Knepley /* After stratification, the migration remotes may not be in root (canonical) order, so we reorder using the leaf numbering */ 1700*00a1aa47SMatthew G. Knepley PetscCall(PetscMalloc1(noldleaves, &permRemote)); 1701*00a1aa47SMatthew G. Knepley for (PetscInt l = 0; l < noldleaves; ++l) permRemote[oldLeaves[l]] = oldRemote[l]; 1702*00a1aa47SMatthew G. Knepley oldRemote = permRemote; 1703*00a1aa47SMatthew G. Knepley } 1704*00a1aa47SMatthew G. Knepley PetscCall(PetscSFBcastBegin(sfOverlap, MPIU_2INT, oldRemote, newRemote, MPI_REPLACE)); 1705*00a1aa47SMatthew G. Knepley PetscCall(PetscSFBcastEnd(sfOverlap, MPIU_2INT, oldRemote, newRemote, MPI_REPLACE)); 1706*00a1aa47SMatthew G. Knepley if (oldLeaves) PetscCall(PetscFree(oldRemote)); 1707*00a1aa47SMatthew G. Knepley PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)sfOverlap), sfMigrationNew)); 1708*00a1aa47SMatthew G. Knepley PetscCall(PetscSFSetGraph(*sfMigrationNew, nroots, nleaves, NULL, PETSC_OWN_POINTER, newRemote, PETSC_OWN_POINTER)); 1709*00a1aa47SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1710*00a1aa47SMatthew G. Knepley } 1711*00a1aa47SMatthew G. Knepley 17123b8f15a2SMatthew G. Knepley /*@C 171370034214SMatthew G. Knepley DMPlexDistribute - Distributes the mesh and any associated sections. 171470034214SMatthew G. Knepley 171520f4b53cSBarry Smith Collective 171670034214SMatthew G. Knepley 1717064ec1f3Sprj- Input Parameters: 171820f4b53cSBarry Smith + dm - The original `DMPLEX` object 171970034214SMatthew G. Knepley - overlap - The overlap of partitions, 0 is the default 172070034214SMatthew G. Knepley 1721064ec1f3Sprj- Output Parameters: 172220f4b53cSBarry Smith + sf - The `PetscSF` used for point distribution, or `NULL` if not needed 172320f4b53cSBarry Smith - dmParallel - The distributed `DMPLEX` object 172470034214SMatthew G. Knepley 172570034214SMatthew G. Knepley Level: intermediate 172670034214SMatthew G. Knepley 172720f4b53cSBarry Smith Note: 172820f4b53cSBarry Smith If the mesh was not distributed, the output `dmParallel` will be `NULL`. 172920f4b53cSBarry Smith 173020f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function 173120f4b53cSBarry Smith representation on the mesh. 173220f4b53cSBarry Smith 173320f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexGetOverlap()` 173470034214SMatthew G. Knepley @*/ 1735d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistribute(DM dm, PetscInt overlap, PetscSF *sf, DM *dmParallel) 1736d71ae5a4SJacob Faibussowitsch { 173770034214SMatthew G. Knepley MPI_Comm comm; 173815078cd4SMichael Lange PetscPartitioner partitioner; 1739f8987ae8SMichael Lange IS cellPart; 1740f8987ae8SMichael Lange PetscSection cellPartSection; 1741cf86098cSMatthew G. Knepley DM dmCoord; 1742f8987ae8SMichael Lange DMLabel lblPartition, lblMigration; 1743874ddda9SLisandro Dalcin PetscSF sfMigration, sfStratified, sfPoint; 17446925d1c4SMatthew G. Knepley VecType vec_type; 174598ba2d7fSLawrence Mitchell PetscBool flg, balance; 1746874ddda9SLisandro Dalcin PetscMPIInt rank, size; 174770034214SMatthew G. Knepley 174870034214SMatthew G. Knepley PetscFunctionBegin; 174970034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1750d5c515a1SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 2); 17514f572ea9SToby Isaac if (sf) PetscAssertPointer(sf, 3); 17524f572ea9SToby Isaac PetscAssertPointer(dmParallel, 4); 175370034214SMatthew G. Knepley 17540c86c063SLisandro Dalcin if (sf) *sf = NULL; 17550c86c063SLisandro Dalcin *dmParallel = NULL; 17569566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 17579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 17589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 17593ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 176070034214SMatthew G. Knepley 17619566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Distribute, dm, 0, 0, 0)); 176215078cd4SMichael Lange /* Create cell partition */ 17639566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0)); 17649566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &cellPartSection)); 17659566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &partitioner)); 17669566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDMPlexPartition(partitioner, dm, NULL, cellPartSection, &cellPart)); 17679566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartSelf, dm, 0, 0, 0)); 1768f8987ae8SMichael Lange { 1769f8987ae8SMichael Lange /* Convert partition to DMLabel */ 1770825f8a23SLisandro Dalcin IS is; 1771825f8a23SLisandro Dalcin PetscHSetI ht; 1772f8987ae8SMichael Lange const PetscInt *points; 17738e330a33SStefano Zampini PetscInt *iranks; 17748e330a33SStefano Zampini PetscInt pStart, pEnd, proc, npoints, poff = 0, nranks; 1775825f8a23SLisandro Dalcin 17769566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point Partition", &lblPartition)); 1777825f8a23SLisandro Dalcin /* Preallocate strata */ 17789566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 17799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1780825f8a23SLisandro Dalcin for (proc = pStart; proc < pEnd; proc++) { 17819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints)); 17829566063dSJacob Faibussowitsch if (npoints) PetscCall(PetscHSetIAdd(ht, proc)); 1783825f8a23SLisandro Dalcin } 17849566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ht, &nranks)); 17859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nranks, &iranks)); 17869566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ht, &poff, iranks)); 17879566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 17889566063dSJacob Faibussowitsch PetscCall(DMLabelAddStrata(lblPartition, nranks, iranks)); 17899566063dSJacob Faibussowitsch PetscCall(PetscFree(iranks)); 1790825f8a23SLisandro Dalcin /* Inline DMPlexPartitionLabelClosure() */ 17919566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellPart, &points)); 17929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1793f8987ae8SMichael Lange for (proc = pStart; proc < pEnd; proc++) { 17949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints)); 1795825f8a23SLisandro Dalcin if (!npoints) continue; 17969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellPartSection, proc, &poff)); 17979566063dSJacob Faibussowitsch PetscCall(DMPlexClosurePoints_Private(dm, npoints, points + poff, &is)); 17989566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(lblPartition, proc, is)); 17999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1800f8987ae8SMichael Lange } 18019566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellPart, &points)); 1802f8987ae8SMichael Lange } 18039566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartSelf, dm, 0, 0, 0)); 18046e203dd9SStefano Zampini 18059566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point migration", &lblMigration)); 18069566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelInvert(dm, lblPartition, NULL, lblMigration)); 18079566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelCreateSF(dm, lblMigration, &sfMigration)); 18089566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, sfMigration, &sfStratified)); 18099566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration)); 181043f7d02bSMichael Lange sfMigration = sfStratified; 18119566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sfMigration)); 18129566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0)); 18139566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-partition_view", &flg)); 181470034214SMatthew G. Knepley if (flg) { 18159566063dSJacob Faibussowitsch PetscCall(DMLabelView(lblPartition, PETSC_VIEWER_STDOUT_(comm))); 18169566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfMigration, PETSC_VIEWER_STDOUT_(comm))); 181770034214SMatthew G. Knepley } 1818f8987ae8SMichael Lange 181915078cd4SMichael Lange /* Create non-overlapping parallel DM and migrate internal data */ 18209566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, dmParallel)); 18219566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*dmParallel, "Parallel Mesh")); 18229566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(dm, sfMigration, *dmParallel)); 182370034214SMatthew G. Knepley 1824a157612eSMichael Lange /* Build the point SF without overlap */ 18259566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitionBalance(dm, &balance)); 18269566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitionBalance(*dmParallel, balance)); 18279566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*dmParallel, sfMigration, PETSC_TRUE, &sfPoint)); 18289566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*dmParallel, sfPoint)); 18295f06a3ddSJed Brown PetscCall(DMPlexMigrateIsoperiodicFaceSF_Internal(dm, *dmParallel, sfMigration)); 18309566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dmParallel, &dmCoord)); 18319566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 18329566063dSJacob Faibussowitsch if (flg) PetscCall(PetscSFView(sfPoint, NULL)); 183370034214SMatthew G. Knepley 1834a157612eSMichael Lange if (overlap > 0) { 183515078cd4SMichael Lange DM dmOverlap; 183615078cd4SMichael Lange PetscSF sfOverlap, sfOverlapPoint; 1837524e35f8SStefano Zampini 1838a157612eSMichael Lange /* Add the partition overlap to the distributed DM */ 18399566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeOverlap(*dmParallel, overlap, &sfOverlap, &dmOverlap)); 18409566063dSJacob Faibussowitsch PetscCall(DMDestroy(dmParallel)); 1841a157612eSMichael Lange *dmParallel = dmOverlap; 1842c389ea9fSToby Isaac if (flg) { 18439566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Overlap Migration SF:\n")); 18449566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfOverlap, NULL)); 1845c389ea9fSToby Isaac } 184643331d4aSMichael Lange 1847f8987ae8SMichael Lange /* Re-map the migration SF to establish the full migration pattern */ 1848*00a1aa47SMatthew G. Knepley PetscCall(DMPlexRemapMigrationSF(sfOverlap, sfMigration, &sfOverlapPoint)); 18499566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfOverlap)); 18509566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration)); 185115078cd4SMichael Lange sfMigration = sfOverlapPoint; 1852c389ea9fSToby Isaac } 1853bf5244c7SMatthew G. Knepley /* Cleanup Partition */ 18549566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblPartition)); 18559566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblMigration)); 18569566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cellPartSection)); 18579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellPart)); 185845480ffeSMatthew G. Knepley /* Copy discretization */ 18599566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *dmParallel)); 18606925d1c4SMatthew G. Knepley PetscCall(DMGetVecType(dm, &vec_type)); 18616925d1c4SMatthew G. Knepley PetscCall(DMSetVecType(*dmParallel, vec_type)); 186266fe0bfeSMatthew G. Knepley /* Create sfNatural */ 186366fe0bfeSMatthew G. Knepley if (dm->useNatural) { 186466fe0bfeSMatthew G. Knepley PetscSection section; 186566fe0bfeSMatthew G. Knepley 1866fc6a3818SBlaise Bourdin PetscCall(DMSetUseNatural(*dmParallel, PETSC_TRUE)); 1867fc6a3818SBlaise Bourdin PetscCall(DMGetLocalSection(dm, §ion)); 1868fc6a3818SBlaise Bourdin 18698aee0f92SAlexis Marboeuf /* First DM with useNatural = PETSC_TRUE is considered natural */ 18708aee0f92SAlexis Marboeuf /* sfMigration and sfNatural are respectively the point and dofs SFs mapping to this natural DM */ 1871fc6a3818SBlaise Bourdin /* Compose with a previous sfNatural if present */ 1872fc6a3818SBlaise Bourdin if (dm->sfNatural) { 1873fc6a3818SBlaise Bourdin PetscSF natSF; 1874fc6a3818SBlaise Bourdin 1875fc6a3818SBlaise Bourdin PetscCall(DMPlexCreateGlobalToNaturalSF(*dmParallel, section, sfMigration, &natSF)); 1876fc6a3818SBlaise Bourdin PetscCall(PetscSFCompose(dm->sfNatural, natSF, &(*dmParallel)->sfNatural)); 1877fc6a3818SBlaise Bourdin PetscCall(PetscSFDestroy(&natSF)); 1878fc6a3818SBlaise Bourdin } else { 1879fc6a3818SBlaise Bourdin PetscCall(DMPlexCreateGlobalToNaturalSF(*dmParallel, section, sfMigration, &(*dmParallel)->sfNatural)); 1880fc6a3818SBlaise Bourdin } 18818aee0f92SAlexis Marboeuf /* Compose with a previous sfMigration if present */ 18828aee0f92SAlexis Marboeuf if (dm->sfMigration) { 18838aee0f92SAlexis Marboeuf PetscSF naturalPointSF; 18848aee0f92SAlexis Marboeuf 18858aee0f92SAlexis Marboeuf PetscCall(PetscSFCompose(dm->sfMigration, sfMigration, &naturalPointSF)); 18868aee0f92SAlexis Marboeuf PetscCall(PetscSFDestroy(&sfMigration)); 18878aee0f92SAlexis Marboeuf sfMigration = naturalPointSF; 18888aee0f92SAlexis Marboeuf } 188966fe0bfeSMatthew G. Knepley } 18905de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *dmParallel)); 1891721cbd76SMatthew G. Knepley /* Cleanup */ 18929371c9d4SSatish Balay if (sf) { 18939371c9d4SSatish Balay *sf = sfMigration; 18949371c9d4SSatish Balay } else PetscCall(PetscSFDestroy(&sfMigration)); 18959566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 18969566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Distribute, dm, 0, 0, 0)); 18973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 189870034214SMatthew G. Knepley } 1899a157612eSMichael Lange 1900a157612eSMichael Lange /*@C 190120f4b53cSBarry Smith DMPlexDistributeOverlap - Add partition overlap to a distributed non-overlapping `DM`. 1902a157612eSMichael Lange 190320f4b53cSBarry Smith Collective 1904a157612eSMichael Lange 1905064ec1f3Sprj- Input Parameters: 190620f4b53cSBarry Smith + dm - The non-overlapping distributed `DMPLEX` object 190757fe9a49SVaclav Hapla - overlap - The overlap of partitions (the same on all ranks) 1908a157612eSMichael Lange 1909064ec1f3Sprj- Output Parameters: 191020f4b53cSBarry Smith + sf - The `PetscSF` used for point distribution 191120f4b53cSBarry Smith - dmOverlap - The overlapping distributed `DMPLEX` object, or `NULL` 1912a157612eSMichael Lange 1913c506a872SMatthew G. Knepley Options Database Keys: 1914c506a872SMatthew G. Knepley + -dm_plex_overlap_labels <name1,name2,...> - List of overlap label names 1915c506a872SMatthew G. Knepley . -dm_plex_overlap_values <int1,int2,...> - List of overlap label values 1916c506a872SMatthew G. Knepley . -dm_plex_overlap_exclude_label <name> - Label used to exclude points from overlap 1917c506a872SMatthew G. Knepley - -dm_plex_overlap_exclude_value <int> - Label value used to exclude points from overlap 1918c506a872SMatthew G. Knepley 1919dccdeccaSVaclav Hapla Level: advanced 1920a157612eSMichael Lange 192120f4b53cSBarry Smith Notes: 192220f4b53cSBarry Smith If the mesh was not distributed, the return value is `NULL`. 192320f4b53cSBarry Smith 192420f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function 192520f4b53cSBarry Smith representation on the mesh. 192620f4b53cSBarry Smith 192720f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMPlexCreateOverlapLabel()`, `DMPlexGetOverlap()` 1928a157612eSMichael Lange @*/ 1929d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeOverlap(DM dm, PetscInt overlap, PetscSF *sf, DM *dmOverlap) 1930d71ae5a4SJacob Faibussowitsch { 1931c506a872SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1932a157612eSMichael Lange MPI_Comm comm; 19333567eaeeSMatthew G. Knepley PetscMPIInt size, rank; 1934a157612eSMichael Lange PetscSection rootSection, leafSection; 1935a157612eSMichael Lange IS rootrank, leafrank; 1936cf86098cSMatthew G. Knepley DM dmCoord; 1937a9f1d5b2SMichael Lange DMLabel lblOverlap; 1938f5bf2dbfSMichael Lange PetscSF sfOverlap, sfStratified, sfPoint; 1939a157612eSMichael Lange 1940a157612eSMichael Lange PetscFunctionBegin; 1941a157612eSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 194257fe9a49SVaclav Hapla PetscValidLogicalCollectiveInt(dm, overlap, 2); 19434f572ea9SToby Isaac if (sf) PetscAssertPointer(sf, 3); 19444f572ea9SToby Isaac PetscAssertPointer(dmOverlap, 4); 1945a157612eSMichael Lange 19460c86c063SLisandro Dalcin if (sf) *sf = NULL; 19470c86c063SLisandro Dalcin *dmOverlap = NULL; 19489566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 19499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 19509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 19513ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 1952c506a872SMatthew G. Knepley { 1953c506a872SMatthew G. Knepley // We need to get options for the _already_distributed mesh, so it must be done here 1954c506a872SMatthew G. Knepley PetscInt overlap; 1955c506a872SMatthew G. Knepley const char *prefix; 1956c506a872SMatthew G. Knepley char oldPrefix[PETSC_MAX_PATH_LEN]; 1957a157612eSMichael Lange 1958c506a872SMatthew G. Knepley oldPrefix[0] = '\0'; 1959c506a872SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 1960c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(oldPrefix, prefix, sizeof(oldPrefix))); 1961c506a872SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, "dist_")); 1962c506a872SMatthew G. Knepley PetscCall(DMPlexGetOverlap(dm, &overlap)); 1963c506a872SMatthew G. Knepley PetscObjectOptionsBegin((PetscObject)dm); 1964dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 1965c506a872SMatthew G. Knepley PetscOptionsEnd(); 1966c506a872SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix[0] == '\0' ? NULL : oldPrefix)); 1967c506a872SMatthew G. Knepley } 19689566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 1969a157612eSMichael Lange /* Compute point overlap with neighbouring processes on the distributed DM */ 19709566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0)); 19719566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &rootSection)); 19729566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &leafSection)); 19739566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeOwnership(dm, rootSection, &rootrank, leafSection, &leafrank)); 1974c506a872SMatthew G. Knepley if (mesh->numOvLabels) PetscCall(DMPlexCreateOverlapLabelFromLabels(dm, mesh->numOvLabels, mesh->ovLabels, mesh->ovValues, mesh->numOvExLabels, mesh->ovExLabels, mesh->ovExValues, rootSection, rootrank, leafSection, leafrank, &lblOverlap)); 1975c506a872SMatthew G. Knepley else PetscCall(DMPlexCreateOverlapLabel(dm, overlap, rootSection, rootrank, leafSection, leafrank, &lblOverlap)); 1976a9f1d5b2SMichael Lange /* Convert overlap label to stratified migration SF */ 19779566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelCreateSF(dm, lblOverlap, &sfOverlap)); 19789566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, sfOverlap, &sfStratified)); 19799566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfOverlap)); 1980a9f1d5b2SMichael Lange sfOverlap = sfStratified; 19819566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfOverlap, "Overlap SF")); 19829566063dSJacob Faibussowitsch PetscCall(PetscSFSetFromOptions(sfOverlap)); 1983a9f1d5b2SMichael Lange 19849566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSection)); 19859566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSection)); 19869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rootrank)); 19879566063dSJacob Faibussowitsch PetscCall(ISDestroy(&leafrank)); 19889566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0)); 1989a157612eSMichael Lange 1990a157612eSMichael Lange /* Build the overlapping DM */ 19919566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, dmOverlap)); 19929566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*dmOverlap, "Parallel Mesh")); 19939566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(dm, sfOverlap, *dmOverlap)); 1994cb54e036SVaclav Hapla /* Store the overlap in the new DM */ 199560667520SVaclav Hapla PetscCall(DMPlexSetOverlap_Plex(*dmOverlap, dm, overlap)); 1996f5bf2dbfSMichael Lange /* Build the new point SF */ 19979566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*dmOverlap, sfOverlap, PETSC_FALSE, &sfPoint)); 19989566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*dmOverlap, sfPoint)); 19999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dmOverlap, &dmCoord)); 20009566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 20016858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(*dmOverlap, &dmCoord)); 20026858538eSMatthew G. Knepley if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 20039566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 2004a157612eSMichael Lange /* Cleanup overlap partition */ 20059566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblOverlap)); 2006a9f1d5b2SMichael Lange if (sf) *sf = sfOverlap; 20079566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfOverlap)); 20089566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 20093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2010a157612eSMichael Lange } 20116462276dSToby Isaac 2012d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap_Plex(DM dm, PetscInt *overlap) 2013d71ae5a4SJacob Faibussowitsch { 2014cb54e036SVaclav Hapla DM_Plex *mesh = (DM_Plex *)dm->data; 2015cb54e036SVaclav Hapla 2016cb54e036SVaclav Hapla PetscFunctionBegin; 2017cb54e036SVaclav Hapla *overlap = mesh->overlap; 20183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2019cb54e036SVaclav Hapla } 2020cb54e036SVaclav Hapla 2021d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap_Plex(DM dm, DM dmSrc, PetscInt overlap) 2022d71ae5a4SJacob Faibussowitsch { 202360667520SVaclav Hapla DM_Plex *mesh = NULL; 202460667520SVaclav Hapla DM_Plex *meshSrc = NULL; 202560667520SVaclav Hapla 202660667520SVaclav Hapla PetscFunctionBegin; 202760667520SVaclav Hapla PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 202860667520SVaclav Hapla mesh = (DM_Plex *)dm->data; 202960667520SVaclav Hapla mesh->overlap = overlap; 203060667520SVaclav Hapla if (dmSrc) { 203160667520SVaclav Hapla PetscValidHeaderSpecificType(dmSrc, DM_CLASSID, 2, DMPLEX); 203260667520SVaclav Hapla meshSrc = (DM_Plex *)dmSrc->data; 203360667520SVaclav Hapla mesh->overlap += meshSrc->overlap; 203460667520SVaclav Hapla } 20353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 203660667520SVaclav Hapla } 203760667520SVaclav Hapla 2038cb54e036SVaclav Hapla /*@ 2039c506a872SMatthew G. Knepley DMPlexGetOverlap - Get the width of the cell overlap 2040cb54e036SVaclav Hapla 204120f4b53cSBarry Smith Not Collective 2042cb54e036SVaclav Hapla 2043cb54e036SVaclav Hapla Input Parameter: 204420f4b53cSBarry Smith . dm - The `DM` 2045cb54e036SVaclav Hapla 2046064ec1f3Sprj- Output Parameter: 2047c506a872SMatthew G. Knepley . overlap - the width of the cell overlap 2048cb54e036SVaclav Hapla 2049cb54e036SVaclav Hapla Level: intermediate 2050cb54e036SVaclav Hapla 205120f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexSetOverlap()`, `DMPlexDistribute()` 2052cb54e036SVaclav Hapla @*/ 2053d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap(DM dm, PetscInt *overlap) 2054d71ae5a4SJacob Faibussowitsch { 2055cb54e036SVaclav Hapla PetscFunctionBegin; 2056cb54e036SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20574f572ea9SToby Isaac PetscAssertPointer(overlap, 2); 2058cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexGetOverlap_C", (DM, PetscInt *), (dm, overlap)); 20593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2060cb54e036SVaclav Hapla } 2061cb54e036SVaclav Hapla 2062c506a872SMatthew G. Knepley /*@ 2063c506a872SMatthew G. Knepley DMPlexSetOverlap - Set the width of the cell overlap 2064c506a872SMatthew G. Knepley 206520f4b53cSBarry Smith Logically Collective 2066c506a872SMatthew G. Knepley 2067c506a872SMatthew G. Knepley Input Parameters: 206820f4b53cSBarry Smith + dm - The `DM` 206920f4b53cSBarry Smith . dmSrc - The `DM` that produced this one, or `NULL` 2070c506a872SMatthew G. Knepley - overlap - the width of the cell overlap 2071c506a872SMatthew G. Knepley 2072c506a872SMatthew G. Knepley Level: intermediate 2073c506a872SMatthew G. Knepley 207420f4b53cSBarry Smith Note: 207520f4b53cSBarry Smith The overlap from `dmSrc` is added to `dm` 207620f4b53cSBarry Smith 207720f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexGetOverlap()`, `DMPlexDistribute()` 2078c506a872SMatthew G. Knepley @*/ 2079d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap(DM dm, DM dmSrc, PetscInt overlap) 2080d71ae5a4SJacob Faibussowitsch { 2081c506a872SMatthew G. Knepley PetscFunctionBegin; 2082c506a872SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2083c506a872SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 3); 2084c506a872SMatthew G. Knepley PetscTryMethod(dm, "DMPlexSetOverlap_C", (DM, DM, PetscInt), (dm, dmSrc, overlap)); 20853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2086c506a872SMatthew G. Knepley } 2087c506a872SMatthew G. Knepley 2088d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault_Plex(DM dm, PetscBool dist) 2089d71ae5a4SJacob Faibussowitsch { 2090e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2091e600fa54SMatthew G. Knepley 2092e600fa54SMatthew G. Knepley PetscFunctionBegin; 2093e600fa54SMatthew G. Knepley mesh->distDefault = dist; 20943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2095e600fa54SMatthew G. Knepley } 2096e600fa54SMatthew G. Knepley 2097e600fa54SMatthew G. Knepley /*@ 209820f4b53cSBarry Smith DMPlexDistributeSetDefault - Set flag indicating whether the `DM` should be distributed by default 2099e600fa54SMatthew G. Knepley 210020f4b53cSBarry Smith Logically Collective 2101e600fa54SMatthew G. Knepley 2102e600fa54SMatthew G. Knepley Input Parameters: 210320f4b53cSBarry Smith + dm - The `DM` 2104e600fa54SMatthew G. Knepley - dist - Flag for distribution 2105e600fa54SMatthew G. Knepley 2106e600fa54SMatthew G. Knepley Level: intermediate 2107e600fa54SMatthew G. Knepley 210820f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributeGetDefault()`, `DMPlexDistribute()` 2109e600fa54SMatthew G. Knepley @*/ 2110d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault(DM dm, PetscBool dist) 2111d71ae5a4SJacob Faibussowitsch { 2112e600fa54SMatthew G. Knepley PetscFunctionBegin; 2113e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2114e600fa54SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, dist, 2); 2115cac4c232SBarry Smith PetscTryMethod(dm, "DMPlexDistributeSetDefault_C", (DM, PetscBool), (dm, dist)); 21163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2117e600fa54SMatthew G. Knepley } 2118e600fa54SMatthew G. Knepley 2119d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault_Plex(DM dm, PetscBool *dist) 2120d71ae5a4SJacob Faibussowitsch { 2121e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2122e600fa54SMatthew G. Knepley 2123e600fa54SMatthew G. Knepley PetscFunctionBegin; 2124e600fa54SMatthew G. Knepley *dist = mesh->distDefault; 21253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2126e600fa54SMatthew G. Knepley } 2127e600fa54SMatthew G. Knepley 2128e600fa54SMatthew G. Knepley /*@ 212920f4b53cSBarry Smith DMPlexDistributeGetDefault - Get flag indicating whether the `DM` should be distributed by default 2130e600fa54SMatthew G. Knepley 213120f4b53cSBarry Smith Not Collective 2132e600fa54SMatthew G. Knepley 2133e600fa54SMatthew G. Knepley Input Parameter: 213420f4b53cSBarry Smith . dm - The `DM` 2135e600fa54SMatthew G. Knepley 2136e600fa54SMatthew G. Knepley Output Parameter: 2137e600fa54SMatthew G. Knepley . dist - Flag for distribution 2138e600fa54SMatthew G. Knepley 2139e600fa54SMatthew G. Knepley Level: intermediate 2140e600fa54SMatthew G. Knepley 214120f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexDistributeSetDefault()`, `DMPlexDistribute()` 2142e600fa54SMatthew G. Knepley @*/ 2143d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault(DM dm, PetscBool *dist) 2144d71ae5a4SJacob Faibussowitsch { 2145e600fa54SMatthew G. Knepley PetscFunctionBegin; 2146e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21474f572ea9SToby Isaac PetscAssertPointer(dist, 2); 2148cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexDistributeGetDefault_C", (DM, PetscBool *), (dm, dist)); 21493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2150e600fa54SMatthew G. Knepley } 2151e600fa54SMatthew G. Knepley 21526462276dSToby Isaac /*@C 215320f4b53cSBarry Smith DMPlexGetGatherDM - Get a copy of the `DMPLEX` that gathers all points on the 21546462276dSToby Isaac root process of the original's communicator. 21556462276dSToby Isaac 215620f4b53cSBarry Smith Collective 215783655b49SVáclav Hapla 2158064ec1f3Sprj- Input Parameter: 215920f4b53cSBarry Smith . dm - the original `DMPLEX` object 21606462276dSToby Isaac 21616462276dSToby Isaac Output Parameters: 216220f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional) 216320f4b53cSBarry Smith - gatherMesh - the gathered `DM` object, or `NULL` 21646462276dSToby Isaac 21656462276dSToby Isaac Level: intermediate 21666462276dSToby Isaac 216720f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `PetscSF`, `DMPlexDistribute()`, `DMPlexGetRedundantDM()` 21686462276dSToby Isaac @*/ 2169d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetGatherDM(DM dm, PetscSF *sf, DM *gatherMesh) 2170d71ae5a4SJacob Faibussowitsch { 21716462276dSToby Isaac MPI_Comm comm; 21726462276dSToby Isaac PetscMPIInt size; 21736462276dSToby Isaac PetscPartitioner oldPart, gatherPart; 21746462276dSToby Isaac 21756462276dSToby Isaac PetscFunctionBegin; 21766462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21774f572ea9SToby Isaac PetscAssertPointer(gatherMesh, 3); 21780c86c063SLisandro Dalcin *gatherMesh = NULL; 2179a13df41bSStefano Zampini if (sf) *sf = NULL; 21806462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 21819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 21823ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 21839566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &oldPart)); 21849566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)oldPart)); 21859566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(comm, &gatherPart)); 21869566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetType(gatherPart, PETSCPARTITIONERGATHER)); 21879566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, gatherPart)); 21889566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, sf, gatherMesh)); 2189a13df41bSStefano Zampini 21909566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, oldPart)); 21919566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&gatherPart)); 21929566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&oldPart)); 21933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21946462276dSToby Isaac } 21956462276dSToby Isaac 21966462276dSToby Isaac /*@C 219720f4b53cSBarry Smith DMPlexGetRedundantDM - Get a copy of the `DMPLEX` that is completely copied on each process. 21986462276dSToby Isaac 219920f4b53cSBarry Smith Collective 220083655b49SVáclav Hapla 2201064ec1f3Sprj- Input Parameter: 220220f4b53cSBarry Smith . dm - the original `DMPLEX` object 22036462276dSToby Isaac 22046462276dSToby Isaac Output Parameters: 220520f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional) 220620f4b53cSBarry Smith - redundantMesh - the redundant `DM` object, or `NULL` 22076462276dSToby Isaac 22086462276dSToby Isaac Level: intermediate 22096462276dSToby Isaac 221060225df5SJacob Faibussowitsch .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetGatherDM()` 22116462276dSToby Isaac @*/ 2212d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRedundantDM(DM dm, PetscSF *sf, DM *redundantMesh) 2213d71ae5a4SJacob Faibussowitsch { 22146462276dSToby Isaac MPI_Comm comm; 22156462276dSToby Isaac PetscMPIInt size, rank; 22166462276dSToby Isaac PetscInt pStart, pEnd, p; 22176462276dSToby Isaac PetscInt numPoints = -1; 2218a13df41bSStefano Zampini PetscSF migrationSF, sfPoint, gatherSF; 22196462276dSToby Isaac DM gatherDM, dmCoord; 22206462276dSToby Isaac PetscSFNode *points; 22216462276dSToby Isaac 22226462276dSToby Isaac PetscFunctionBegin; 22236462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22244f572ea9SToby Isaac PetscAssertPointer(redundantMesh, 3); 22250c86c063SLisandro Dalcin *redundantMesh = NULL; 22266462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 22279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 222868dbc166SMatthew G. Knepley if (size == 1) { 22299566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 223068dbc166SMatthew G. Knepley *redundantMesh = dm; 2231a13df41bSStefano Zampini if (sf) *sf = NULL; 22323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 223368dbc166SMatthew G. Knepley } 22349566063dSJacob Faibussowitsch PetscCall(DMPlexGetGatherDM(dm, &gatherSF, &gatherDM)); 22353ba16761SJacob Faibussowitsch if (!gatherDM) PetscFunctionReturn(PETSC_SUCCESS); 22369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 22379566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(gatherDM, &pStart, &pEnd)); 22386462276dSToby Isaac numPoints = pEnd - pStart; 22399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numPoints, 1, MPIU_INT, 0, comm)); 22409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &points)); 22419566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &migrationSF)); 22426462276dSToby Isaac for (p = 0; p < numPoints; p++) { 22436462276dSToby Isaac points[p].index = p; 22446462276dSToby Isaac points[p].rank = 0; 22456462276dSToby Isaac } 22469566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(migrationSF, pEnd - pStart, numPoints, NULL, PETSC_OWN_POINTER, points, PETSC_OWN_POINTER)); 22479566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, redundantMesh)); 22489566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*redundantMesh, "Redundant Mesh")); 22499566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(gatherDM, migrationSF, *redundantMesh)); 22502e28cf0cSVaclav Hapla /* This is to express that all point are in overlap */ 22512e28cf0cSVaclav Hapla PetscCall(DMPlexSetOverlap_Plex(*redundantMesh, NULL, PETSC_MAX_INT)); 22529566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*redundantMesh, migrationSF, PETSC_FALSE, &sfPoint)); 22539566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*redundantMesh, sfPoint)); 22549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*redundantMesh, &dmCoord)); 22559566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 22569566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 2257a13df41bSStefano Zampini if (sf) { 2258a13df41bSStefano Zampini PetscSF tsf; 2259a13df41bSStefano Zampini 22609566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(gatherSF, migrationSF, &tsf)); 22619566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, tsf, sf)); 22629566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&tsf)); 2263a13df41bSStefano Zampini } 22649566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&migrationSF)); 22659566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&gatherSF)); 22669566063dSJacob Faibussowitsch PetscCall(DMDestroy(&gatherDM)); 22679566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *redundantMesh)); 22685de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *redundantMesh)); 22693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22706462276dSToby Isaac } 22715fa78c88SVaclav Hapla 22725fa78c88SVaclav Hapla /*@ 227320f4b53cSBarry Smith DMPlexIsDistributed - Find out whether this `DM` is distributed, i.e. more than one rank owns some points. 22745fa78c88SVaclav Hapla 22755fa78c88SVaclav Hapla Collective 22765fa78c88SVaclav Hapla 22775fa78c88SVaclav Hapla Input Parameter: 227820f4b53cSBarry Smith . dm - The `DM` object 22795fa78c88SVaclav Hapla 22805fa78c88SVaclav Hapla Output Parameter: 228120f4b53cSBarry Smith . distributed - Flag whether the `DM` is distributed 22825fa78c88SVaclav Hapla 22835fa78c88SVaclav Hapla Level: intermediate 22845fa78c88SVaclav Hapla 22855fa78c88SVaclav Hapla Notes: 22865fa78c88SVaclav Hapla This currently finds out whether at least two ranks have any DAG points. 228720f4b53cSBarry Smith This involves `MPI_Allreduce()` with one integer. 22885fa78c88SVaclav Hapla The result is currently not stashed so every call to this routine involves this global communication. 22895fa78c88SVaclav Hapla 229060225df5SJacob Faibussowitsch .seealso: `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetOverlap()`, `DMPlexIsInterpolated()` 22915fa78c88SVaclav Hapla @*/ 2292d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsDistributed(DM dm, PetscBool *distributed) 2293d71ae5a4SJacob Faibussowitsch { 22945fa78c88SVaclav Hapla PetscInt pStart, pEnd, count; 22955fa78c88SVaclav Hapla MPI_Comm comm; 229635d70e31SStefano Zampini PetscMPIInt size; 22975fa78c88SVaclav Hapla 22985fa78c88SVaclav Hapla PetscFunctionBegin; 22995fa78c88SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23004f572ea9SToby Isaac PetscAssertPointer(distributed, 2); 23019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 23029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 23039371c9d4SSatish Balay if (size == 1) { 23049371c9d4SSatish Balay *distributed = PETSC_FALSE; 23053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23069371c9d4SSatish Balay } 23079566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 230835d70e31SStefano Zampini count = (pEnd - pStart) > 0 ? 1 : 0; 2309712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &count, 1, MPIU_INT, MPI_SUM, comm)); 23105fa78c88SVaclav Hapla *distributed = count > 1 ? PETSC_TRUE : PETSC_FALSE; 23113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23125fa78c88SVaclav Hapla } 23131d1f2f2aSksagiyam 23141d1f2f2aSksagiyam /*@C 23151d1f2f2aSksagiyam DMPlexDistributionSetName - Set the name of the specific parallel distribution 23161d1f2f2aSksagiyam 23171d1f2f2aSksagiyam Input Parameters: 231820f4b53cSBarry Smith + dm - The `DM` 23191d1f2f2aSksagiyam - name - The name of the specific parallel distribution 23201d1f2f2aSksagiyam 23211d1f2f2aSksagiyam Level: developer 23221d1f2f2aSksagiyam 232320f4b53cSBarry Smith Note: 232420f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's 232520f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under 232620f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()` 232720f4b53cSBarry Smith loads the parallel distribution stored in file under this name. 232820f4b53cSBarry Smith 232920f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionGetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()` 23301d1f2f2aSksagiyam @*/ 2331d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionSetName(DM dm, const char name[]) 2332d71ae5a4SJacob Faibussowitsch { 23331d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data; 23341d1f2f2aSksagiyam 23351d1f2f2aSksagiyam PetscFunctionBegin; 23361d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 23374f572ea9SToby Isaac if (name) PetscAssertPointer(name, 2); 23381d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 23391d1f2f2aSksagiyam PetscCall(PetscStrallocpy(name, &mesh->distributionName)); 23403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23411d1f2f2aSksagiyam } 23421d1f2f2aSksagiyam 23431d1f2f2aSksagiyam /*@C 23441d1f2f2aSksagiyam DMPlexDistributionGetName - Retrieve the name of the specific parallel distribution 23451d1f2f2aSksagiyam 23461d1f2f2aSksagiyam Input Parameter: 234720f4b53cSBarry Smith . dm - The `DM` 23481d1f2f2aSksagiyam 23491d1f2f2aSksagiyam Output Parameter: 23501d1f2f2aSksagiyam . name - The name of the specific parallel distribution 23511d1f2f2aSksagiyam 23521d1f2f2aSksagiyam Level: developer 23531d1f2f2aSksagiyam 235420f4b53cSBarry Smith Note: 235520f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's 235620f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under 235720f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()` 235820f4b53cSBarry Smith loads the parallel distribution stored in file under this name. 235920f4b53cSBarry Smith 236020f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionSetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()` 23611d1f2f2aSksagiyam @*/ 2362d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionGetName(DM dm, const char *name[]) 2363d71ae5a4SJacob Faibussowitsch { 23641d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data; 23651d1f2f2aSksagiyam 23661d1f2f2aSksagiyam PetscFunctionBegin; 23671d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 23684f572ea9SToby Isaac PetscAssertPointer(name, 2); 23691d1f2f2aSksagiyam *name = mesh->distributionName; 23703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23711d1f2f2aSksagiyam } 2372