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 9*20f4b53cSBarry Smith . user - The user callback, may be `NULL` (to clear the callback) 10*20f4b53cSBarry Smith - ctx - context for callback evaluation, may be `NULL` 113c1f0c11SLawrence Mitchell 123c1f0c11SLawrence Mitchell Level: advanced 133c1f0c11SLawrence Mitchell 143c1f0c11SLawrence Mitchell Notes: 15*20f4b53cSBarry Smith The caller of `DMPlexGetAdjacency()` may need to arrange that a large enough array is available for the adjacency. 163c1f0c11SLawrence Mitchell 17*20f4b53cSBarry Smith Any setting here overrides other configuration of `DMPLEX` adjacency determination. 183c1f0c11SLawrence Mitchell 19*20f4b53cSBarry 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: 36*20f4b53cSBarry 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 44*20f4b53cSBarry 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: 61*20f4b53cSBarry 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 66*20f4b53cSBarry 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: 82*20f4b53cSBarry 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 89*20f4b53cSBarry 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); 97064a246eSJacob Faibussowitsch PetscValidBoolPointer(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: 264*20f4b53cSBarry Smith + dm - The `DM` object 2656b867d5aSJose E. Roman - p - The point 26670034214SMatthew G. Knepley 2676b867d5aSJose E. Roman Input/Output Parameters: 268*20f4b53cSBarry 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 270*20f4b53cSBarry 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: 276*20f4b53cSBarry Smith The user must `PetscFree()` the `adj` array if it was not passed in. 27770034214SMatthew G. Knepley 278*20f4b53cSBarry 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); 286dadcf809SJacob Faibussowitsch PetscValidIntPointer(adjSize, 3); 28770034214SMatthew G. Knepley PetscValidPointer(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 /*@ 295*20f4b53cSBarry Smith DMPlexCreateTwoSidedProcessSF - Create an `PetscSF` which just has process connectivity 296b0a623aaSMatthew G. Knepley 297*20f4b53cSBarry Smith Collective 298b0a623aaSMatthew G. Knepley 299b0a623aaSMatthew G. Knepley Input Parameters: 300*20f4b53cSBarry Smith + dm - The `DM` 301*20f4b53cSBarry Smith . sfPoint - The `PetscSF` which encodes point connectivity 302*20f4b53cSBarry Smith . rootRankSection - to be documented 303*20f4b53cSBarry Smith . rootRanks - to be documented 304*20f4b53cSBarry Smith . leftRankSection - to be documented 305*20f4b53cSBarry Smith - leafRanks - to be documented 306b0a623aaSMatthew G. Knepley 307b0a623aaSMatthew G. Knepley Output Parameters: 308*20f4b53cSBarry Smith + processRanks - A list of process neighbors, or `NULL` 309*20f4b53cSBarry Smith - sfProcess - An `PetscSF` encoding the two-sided process connectivity, or `NULL` 310b0a623aaSMatthew G. Knepley 311b0a623aaSMatthew G. Knepley Level: developer 312b0a623aaSMatthew G. Knepley 313*20f4b53cSBarry 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); 329ad540459SPierre Jolivet if (processRanks) PetscValidPointer(processRanks, 7); 330ad540459SPierre Jolivet if (sfProcess) PetscValidPointer(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 392*20f4b53cSBarry Smith Collective 393b0a623aaSMatthew G. Knepley 394b0a623aaSMatthew G. Knepley Input Parameter: 395*20f4b53cSBarry 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 405*20f4b53cSBarry 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 446*20f4b53cSBarry Smith Collective 447b0a623aaSMatthew G. Knepley 448b0a623aaSMatthew G. Knepley Input Parameters: 449*20f4b53cSBarry 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: 457*20f4b53cSBarry Smith . ovLabel - `DMLabel` containing remote overlap contributions as point/rank pairings 458b0a623aaSMatthew G. Knepley 459b0a623aaSMatthew G. Knepley Level: developer 460b0a623aaSMatthew G. Knepley 461*20f4b53cSBarry 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 604*20f4b53cSBarry Smith Collective 605c506a872SMatthew G. Knepley 606c506a872SMatthew G. Knepley Input Parameters: 607*20f4b53cSBarry 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 612*20f4b53cSBarry Smith . exLabel - An array of labels indicating points to be excluded, or `NULL` 613*20f4b53cSBarry 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: 620*20f4b53cSBarry Smith . ovLabel - `DMLabel` containing remote overlap contributions as point/rank pairings 621*20f4b53cSBarry Smith 622*20f4b53cSBarry 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 627*20f4b53cSBarry 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 726*20f4b53cSBarry Smith DMPlexCreateOverlapMigrationSF - Create a `PetscSF` describing the new mesh distribution to make the overlap described by the input `PetscSF` 72724cc2ca5SMatthew G. Knepley 728*20f4b53cSBarry Smith Collective 72924cc2ca5SMatthew G. Knepley 73024cc2ca5SMatthew G. Knepley Input Parameters: 731*20f4b53cSBarry Smith + dm - The `DM` 732*20f4b53cSBarry Smith - overlapSF - The `PetscSF` mapping ghost points in overlap to owner points on other processes 73324cc2ca5SMatthew G. Knepley 734064ec1f3Sprj- Output Parameter: 735*20f4b53cSBarry 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 739*20f4b53cSBarry 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 845*20f4b53cSBarry Smith Level: developer 846*20f4b53cSBarry Smith 847412e9a14SMatthew G. Knepley Note: 848412e9a14SMatthew G. Knepley This lexicographically sorts by (depth, cellType) 849412e9a14SMatthew G. Knepley 850*20f4b53cSBarry 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 /*@ 961*20f4b53cSBarry Smith DMPlexDistributeField - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 96270034214SMatthew G. Knepley 963*20f4b53cSBarry Smith Collective 96470034214SMatthew G. Knepley 96570034214SMatthew G. Knepley Input Parameters: 966*20f4b53cSBarry Smith + dm - The `DMPLEX` object 967*20f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 968*20f4b53cSBarry 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: 972*20f4b53cSBarry 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 977*20f4b53cSBarry 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 /*@ 1007*20f4b53cSBarry Smith DMPlexDistributeFieldIS - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 100870034214SMatthew G. Knepley 1009*20f4b53cSBarry Smith Collective 101070034214SMatthew G. Knepley 101170034214SMatthew G. Knepley Input Parameters: 1012*20f4b53cSBarry Smith + dm - The `DMPLEX` object 1013*20f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 1014*20f4b53cSBarry Smith . originalSection - The `PetscSection` for existing data layout 101570034214SMatthew G. Knepley - originalIS - The existing data 101670034214SMatthew G. Knepley 101770034214SMatthew G. Knepley Output Parameters: 1018*20f4b53cSBarry 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 1023*20f4b53cSBarry 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 /*@ 1051*20f4b53cSBarry Smith DMPlexDistributeData - Distribute field data to match a given `PetscSF`, usually the `PetscSF` from mesh distribution 105270034214SMatthew G. Knepley 1053*20f4b53cSBarry Smith Collective 105470034214SMatthew G. Knepley 105570034214SMatthew G. Knepley Input Parameters: 1056*20f4b53cSBarry Smith + dm - The `DMPLEX` object 1057*20f4b53cSBarry Smith . pointSF - The `PetscSF` describing the communication pattern 1058*20f4b53cSBarry 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: 1063*20f4b53cSBarry 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 1068*20f4b53cSBarry 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 /*@ 1396*20f4b53cSBarry Smith DMPlexSetPartitionBalance - Should distribution of the `DM` attempt to balance the shared point partition? 139798ba2d7fSLawrence Mitchell 139898ba2d7fSLawrence Mitchell Input Parameters: 1399*20f4b53cSBarry Smith + dm - The `DMPLEX` object 140098ba2d7fSLawrence Mitchell - flg - Balance the partition? 140198ba2d7fSLawrence Mitchell 140298ba2d7fSLawrence Mitchell Level: intermediate 140398ba2d7fSLawrence Mitchell 1404*20f4b53cSBarry 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 /*@ 1416*20f4b53cSBarry Smith DMPlexGetPartitionBalance - Does distribution of the `DM` attempt to balance the shared point partition? 141798ba2d7fSLawrence Mitchell 141898ba2d7fSLawrence Mitchell Input Parameter: 1419*20f4b53cSBarry 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 1426*20f4b53cSBarry 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); 1434534a8f05SLisandro Dalcin PetscValidBoolPointer(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 1464*20f4b53cSBarry Smith DMPlexCreatePointSF - Build a point `PetscSF` from an `PetscSF` describing a point migration 1465f5bf2dbfSMichael Lange 1466064ec1f3Sprj- Input Parameters: 1467*20f4b53cSBarry 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: 1472*20f4b53cSBarry Smith . pointSF - The star forest describing the point overlap in the remapped `DM` 14733618482eSVaclav Hapla 1474f5bf2dbfSMichael Lange Level: developer 1475f5bf2dbfSMichael Lange 1476*20f4b53cSBarry Smith Note: 1477*20f4b53cSBarry Smith Output `pointSF` is guaranteed to have the array of local indices (leaves) sorted. 1478*20f4b53cSBarry Smith 1479*20f4b53cSBarry 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 1595*20f4b53cSBarry Smith DMPlexMigrate - Migrates internal `DM` data over the supplied star forest 159615078cd4SMichael Lange 1597*20f4b53cSBarry Smith Collective 159883655b49SVáclav Hapla 1599064ec1f3Sprj- Input Parameters: 1600*20f4b53cSBarry 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: 1604*20f4b53cSBarry Smith . targetDM - The target `DMPLEX` object 160515078cd4SMichael Lange 1606b9f40539SMichael Lange Level: intermediate 160715078cd4SMichael Lange 1608*20f4b53cSBarry 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 16693b8f15a2SMatthew G. Knepley /*@C 167070034214SMatthew G. Knepley DMPlexDistribute - Distributes the mesh and any associated sections. 167170034214SMatthew G. Knepley 1672*20f4b53cSBarry Smith Collective 167370034214SMatthew G. Knepley 1674064ec1f3Sprj- Input Parameters: 1675*20f4b53cSBarry Smith + dm - The original `DMPLEX` object 167670034214SMatthew G. Knepley - overlap - The overlap of partitions, 0 is the default 167770034214SMatthew G. Knepley 1678064ec1f3Sprj- Output Parameters: 1679*20f4b53cSBarry Smith + sf - The `PetscSF` used for point distribution, or `NULL` if not needed 1680*20f4b53cSBarry Smith - dmParallel - The distributed `DMPLEX` object 168170034214SMatthew G. Knepley 168270034214SMatthew G. Knepley Level: intermediate 168370034214SMatthew G. Knepley 1684*20f4b53cSBarry Smith Note: 1685*20f4b53cSBarry Smith If the mesh was not distributed, the output `dmParallel` will be `NULL`. 1686*20f4b53cSBarry Smith 1687*20f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function 1688*20f4b53cSBarry Smith representation on the mesh. 1689*20f4b53cSBarry Smith 1690*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexGetOverlap()` 169170034214SMatthew G. Knepley @*/ 1692d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistribute(DM dm, PetscInt overlap, PetscSF *sf, DM *dmParallel) 1693d71ae5a4SJacob Faibussowitsch { 169470034214SMatthew G. Knepley MPI_Comm comm; 169515078cd4SMichael Lange PetscPartitioner partitioner; 1696f8987ae8SMichael Lange IS cellPart; 1697f8987ae8SMichael Lange PetscSection cellPartSection; 1698cf86098cSMatthew G. Knepley DM dmCoord; 1699f8987ae8SMichael Lange DMLabel lblPartition, lblMigration; 1700874ddda9SLisandro Dalcin PetscSF sfMigration, sfStratified, sfPoint; 170198ba2d7fSLawrence Mitchell PetscBool flg, balance; 1702874ddda9SLisandro Dalcin PetscMPIInt rank, size; 170370034214SMatthew G. Knepley 170470034214SMatthew G. Knepley PetscFunctionBegin; 170570034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1706d5c515a1SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 2); 1707d5c515a1SMatthew G. Knepley if (sf) PetscValidPointer(sf, 3); 1708d5c515a1SMatthew G. Knepley PetscValidPointer(dmParallel, 4); 170970034214SMatthew G. Knepley 17100c86c063SLisandro Dalcin if (sf) *sf = NULL; 17110c86c063SLisandro Dalcin *dmParallel = NULL; 17129566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 17139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 17149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 17153ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 171670034214SMatthew G. Knepley 17179566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Distribute, dm, 0, 0, 0)); 171815078cd4SMichael Lange /* Create cell partition */ 17199566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0)); 17209566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &cellPartSection)); 17219566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &partitioner)); 17229566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDMPlexPartition(partitioner, dm, NULL, cellPartSection, &cellPart)); 17239566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_PartSelf, dm, 0, 0, 0)); 1724f8987ae8SMichael Lange { 1725f8987ae8SMichael Lange /* Convert partition to DMLabel */ 1726825f8a23SLisandro Dalcin IS is; 1727825f8a23SLisandro Dalcin PetscHSetI ht; 1728f8987ae8SMichael Lange const PetscInt *points; 17298e330a33SStefano Zampini PetscInt *iranks; 17308e330a33SStefano Zampini PetscInt pStart, pEnd, proc, npoints, poff = 0, nranks; 1731825f8a23SLisandro Dalcin 17329566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point Partition", &lblPartition)); 1733825f8a23SLisandro Dalcin /* Preallocate strata */ 17349566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 17359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1736825f8a23SLisandro Dalcin for (proc = pStart; proc < pEnd; proc++) { 17379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints)); 17389566063dSJacob Faibussowitsch if (npoints) PetscCall(PetscHSetIAdd(ht, proc)); 1739825f8a23SLisandro Dalcin } 17409566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ht, &nranks)); 17419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nranks, &iranks)); 17429566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ht, &poff, iranks)); 17439566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 17449566063dSJacob Faibussowitsch PetscCall(DMLabelAddStrata(lblPartition, nranks, iranks)); 17459566063dSJacob Faibussowitsch PetscCall(PetscFree(iranks)); 1746825f8a23SLisandro Dalcin /* Inline DMPlexPartitionLabelClosure() */ 17479566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellPart, &points)); 17489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1749f8987ae8SMichael Lange for (proc = pStart; proc < pEnd; proc++) { 17509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellPartSection, proc, &npoints)); 1751825f8a23SLisandro Dalcin if (!npoints) continue; 17529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellPartSection, proc, &poff)); 17539566063dSJacob Faibussowitsch PetscCall(DMPlexClosurePoints_Private(dm, npoints, points + poff, &is)); 17549566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(lblPartition, proc, is)); 17559566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1756f8987ae8SMichael Lange } 17579566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cellPart, &points)); 1758f8987ae8SMichael Lange } 17599566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_PartSelf, dm, 0, 0, 0)); 17606e203dd9SStefano Zampini 17619566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "Point migration", &lblMigration)); 17629566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelInvert(dm, lblPartition, NULL, lblMigration)); 17639566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelCreateSF(dm, lblMigration, &sfMigration)); 17649566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, sfMigration, &sfStratified)); 17659566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration)); 176643f7d02bSMichael Lange sfMigration = sfStratified; 17679566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sfMigration)); 17689566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0)); 17699566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-partition_view", &flg)); 177070034214SMatthew G. Knepley if (flg) { 17719566063dSJacob Faibussowitsch PetscCall(DMLabelView(lblPartition, PETSC_VIEWER_STDOUT_(comm))); 17729566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfMigration, PETSC_VIEWER_STDOUT_(comm))); 177370034214SMatthew G. Knepley } 1774f8987ae8SMichael Lange 177515078cd4SMichael Lange /* Create non-overlapping parallel DM and migrate internal data */ 17769566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, dmParallel)); 17779566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*dmParallel, "Parallel Mesh")); 17789566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(dm, sfMigration, *dmParallel)); 177970034214SMatthew G. Knepley 1780a157612eSMichael Lange /* Build the point SF without overlap */ 17819566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitionBalance(dm, &balance)); 17829566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitionBalance(*dmParallel, balance)); 17839566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*dmParallel, sfMigration, PETSC_TRUE, &sfPoint)); 17849566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*dmParallel, sfPoint)); 17855f06a3ddSJed Brown PetscCall(DMPlexMigrateIsoperiodicFaceSF_Internal(dm, *dmParallel, sfMigration)); 17869566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dmParallel, &dmCoord)); 17879566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 17889566063dSJacob Faibussowitsch if (flg) PetscCall(PetscSFView(sfPoint, NULL)); 178970034214SMatthew G. Knepley 1790a157612eSMichael Lange if (overlap > 0) { 179115078cd4SMichael Lange DM dmOverlap; 179257f290daSMatthew G. Knepley PetscInt nroots, nleaves, noldleaves, l; 179357f290daSMatthew G. Knepley const PetscInt *oldLeaves; 179457f290daSMatthew G. Knepley PetscSFNode *newRemote, *permRemote; 179515078cd4SMichael Lange const PetscSFNode *oldRemote; 179615078cd4SMichael Lange PetscSF sfOverlap, sfOverlapPoint; 1797524e35f8SStefano Zampini 1798a157612eSMichael Lange /* Add the partition overlap to the distributed DM */ 17999566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeOverlap(*dmParallel, overlap, &sfOverlap, &dmOverlap)); 18009566063dSJacob Faibussowitsch PetscCall(DMDestroy(dmParallel)); 1801a157612eSMichael Lange *dmParallel = dmOverlap; 1802c389ea9fSToby Isaac if (flg) { 18039566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Overlap Migration SF:\n")); 18049566063dSJacob Faibussowitsch PetscCall(PetscSFView(sfOverlap, NULL)); 1805c389ea9fSToby Isaac } 180643331d4aSMichael Lange 1807f8987ae8SMichael Lange /* Re-map the migration SF to establish the full migration pattern */ 18089566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfMigration, &nroots, &noldleaves, &oldLeaves, &oldRemote)); 18099566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfOverlap, NULL, &nleaves, NULL, NULL)); 18109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &newRemote)); 181157f290daSMatthew G. Knepley /* oldRemote: original root point mapping to original leaf point 181257f290daSMatthew G. Knepley newRemote: original leaf point mapping to overlapped leaf point */ 181357f290daSMatthew G. Knepley if (oldLeaves) { 181473e69a6aSMatthew G. Knepley /* After stratification, the migration remotes may not be in root (canonical) order, so we reorder using the leaf numbering */ 18159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(noldleaves, &permRemote)); 181657f290daSMatthew G. Knepley for (l = 0; l < noldleaves; ++l) permRemote[oldLeaves[l]] = oldRemote[l]; 181757f290daSMatthew G. Knepley oldRemote = permRemote; 181857f290daSMatthew G. Knepley } 18199566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfOverlap, MPIU_2INT, oldRemote, newRemote, MPI_REPLACE)); 18209566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfOverlap, MPIU_2INT, oldRemote, newRemote, MPI_REPLACE)); 18219566063dSJacob Faibussowitsch if (oldLeaves) PetscCall(PetscFree(oldRemote)); 18229566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sfOverlapPoint)); 18239566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfOverlapPoint, nroots, nleaves, NULL, PETSC_OWN_POINTER, newRemote, PETSC_OWN_POINTER)); 18249566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfOverlap)); 18259566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfMigration)); 182615078cd4SMichael Lange sfMigration = sfOverlapPoint; 1827c389ea9fSToby Isaac } 1828bf5244c7SMatthew G. Knepley /* Cleanup Partition */ 18299566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblPartition)); 18309566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblMigration)); 18319566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cellPartSection)); 18329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellPart)); 183345480ffeSMatthew G. Knepley /* Copy discretization */ 18349566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *dmParallel)); 183566fe0bfeSMatthew G. Knepley /* Create sfNatural */ 183666fe0bfeSMatthew G. Knepley if (dm->useNatural) { 183766fe0bfeSMatthew G. Knepley PetscSection section; 183866fe0bfeSMatthew G. Knepley 1839fc6a3818SBlaise Bourdin PetscCall(DMSetUseNatural(*dmParallel, PETSC_TRUE)); 1840fc6a3818SBlaise Bourdin PetscCall(DMGetLocalSection(dm, §ion)); 1841fc6a3818SBlaise Bourdin 18428aee0f92SAlexis Marboeuf /* First DM with useNatural = PETSC_TRUE is considered natural */ 18438aee0f92SAlexis Marboeuf /* sfMigration and sfNatural are respectively the point and dofs SFs mapping to this natural DM */ 1844fc6a3818SBlaise Bourdin /* Compose with a previous sfNatural if present */ 1845fc6a3818SBlaise Bourdin if (dm->sfNatural) { 1846fc6a3818SBlaise Bourdin PetscSF natSF; 1847fc6a3818SBlaise Bourdin 1848fc6a3818SBlaise Bourdin PetscCall(DMPlexCreateGlobalToNaturalSF(*dmParallel, section, sfMigration, &natSF)); 1849fc6a3818SBlaise Bourdin PetscCall(PetscSFCompose(dm->sfNatural, natSF, &(*dmParallel)->sfNatural)); 1850fc6a3818SBlaise Bourdin PetscCall(PetscSFDestroy(&natSF)); 1851fc6a3818SBlaise Bourdin } else { 1852fc6a3818SBlaise Bourdin PetscCall(DMPlexCreateGlobalToNaturalSF(*dmParallel, section, sfMigration, &(*dmParallel)->sfNatural)); 1853fc6a3818SBlaise Bourdin } 18548aee0f92SAlexis Marboeuf /* Compose with a previous sfMigration if present */ 18558aee0f92SAlexis Marboeuf if (dm->sfMigration) { 18568aee0f92SAlexis Marboeuf PetscSF naturalPointSF; 18578aee0f92SAlexis Marboeuf 18588aee0f92SAlexis Marboeuf PetscCall(PetscSFCompose(dm->sfMigration, sfMigration, &naturalPointSF)); 18598aee0f92SAlexis Marboeuf PetscCall(PetscSFDestroy(&sfMigration)); 18608aee0f92SAlexis Marboeuf sfMigration = naturalPointSF; 18618aee0f92SAlexis Marboeuf } 186266fe0bfeSMatthew G. Knepley } 18635de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *dmParallel)); 1864721cbd76SMatthew G. Knepley /* Cleanup */ 18659371c9d4SSatish Balay if (sf) { 18669371c9d4SSatish Balay *sf = sfMigration; 18679371c9d4SSatish Balay } else PetscCall(PetscSFDestroy(&sfMigration)); 18689566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 18699566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Distribute, dm, 0, 0, 0)); 18703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 187170034214SMatthew G. Knepley } 1872a157612eSMichael Lange 1873a157612eSMichael Lange /*@C 1874*20f4b53cSBarry Smith DMPlexDistributeOverlap - Add partition overlap to a distributed non-overlapping `DM`. 1875a157612eSMichael Lange 1876*20f4b53cSBarry Smith Collective 1877a157612eSMichael Lange 1878064ec1f3Sprj- Input Parameters: 1879*20f4b53cSBarry Smith + dm - The non-overlapping distributed `DMPLEX` object 188057fe9a49SVaclav Hapla - overlap - The overlap of partitions (the same on all ranks) 1881a157612eSMichael Lange 1882064ec1f3Sprj- Output Parameters: 1883*20f4b53cSBarry Smith + sf - The `PetscSF` used for point distribution 1884*20f4b53cSBarry Smith - dmOverlap - The overlapping distributed `DMPLEX` object, or `NULL` 1885a157612eSMichael Lange 1886c506a872SMatthew G. Knepley Options Database Keys: 1887c506a872SMatthew G. Knepley + -dm_plex_overlap_labels <name1,name2,...> - List of overlap label names 1888c506a872SMatthew G. Knepley . -dm_plex_overlap_values <int1,int2,...> - List of overlap label values 1889c506a872SMatthew G. Knepley . -dm_plex_overlap_exclude_label <name> - Label used to exclude points from overlap 1890c506a872SMatthew G. Knepley - -dm_plex_overlap_exclude_value <int> - Label value used to exclude points from overlap 1891c506a872SMatthew G. Knepley 1892dccdeccaSVaclav Hapla Level: advanced 1893a157612eSMichael Lange 1894*20f4b53cSBarry Smith Notes: 1895*20f4b53cSBarry Smith If the mesh was not distributed, the return value is `NULL`. 1896*20f4b53cSBarry Smith 1897*20f4b53cSBarry Smith The user can control the definition of adjacency for the mesh using `DMSetAdjacency()`. They should choose the combination appropriate for the function 1898*20f4b53cSBarry Smith representation on the mesh. 1899*20f4b53cSBarry Smith 1900*20f4b53cSBarry Smith .seealso: `DMPLEX`, `PetscSF`, `DM`, `DMPlexCreate()`, `DMSetAdjacency()`, `DMPlexDistribute()`, `DMPlexCreateOverlapLabel()`, `DMPlexGetOverlap()` 1901a157612eSMichael Lange @*/ 1902d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeOverlap(DM dm, PetscInt overlap, PetscSF *sf, DM *dmOverlap) 1903d71ae5a4SJacob Faibussowitsch { 1904c506a872SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 1905a157612eSMichael Lange MPI_Comm comm; 19063567eaeeSMatthew G. Knepley PetscMPIInt size, rank; 1907a157612eSMichael Lange PetscSection rootSection, leafSection; 1908a157612eSMichael Lange IS rootrank, leafrank; 1909cf86098cSMatthew G. Knepley DM dmCoord; 1910a9f1d5b2SMichael Lange DMLabel lblOverlap; 1911f5bf2dbfSMichael Lange PetscSF sfOverlap, sfStratified, sfPoint; 1912a157612eSMichael Lange 1913a157612eSMichael Lange PetscFunctionBegin; 1914a157612eSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 191557fe9a49SVaclav Hapla PetscValidLogicalCollectiveInt(dm, overlap, 2); 1916a157612eSMichael Lange if (sf) PetscValidPointer(sf, 3); 1917a157612eSMichael Lange PetscValidPointer(dmOverlap, 4); 1918a157612eSMichael Lange 19190c86c063SLisandro Dalcin if (sf) *sf = NULL; 19200c86c063SLisandro Dalcin *dmOverlap = NULL; 19219566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 19229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 19239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 19243ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 1925c506a872SMatthew G. Knepley { 1926c506a872SMatthew G. Knepley // We need to get options for the _already_distributed mesh, so it must be done here 1927c506a872SMatthew G. Knepley PetscInt overlap; 1928c506a872SMatthew G. Knepley const char *prefix; 1929c506a872SMatthew G. Knepley char oldPrefix[PETSC_MAX_PATH_LEN]; 1930a157612eSMichael Lange 1931c506a872SMatthew G. Knepley oldPrefix[0] = '\0'; 1932c506a872SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 1933c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(oldPrefix, prefix, sizeof(oldPrefix))); 1934c506a872SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, "dist_")); 1935c506a872SMatthew G. Knepley PetscCall(DMPlexGetOverlap(dm, &overlap)); 1936c506a872SMatthew G. Knepley PetscObjectOptionsBegin((PetscObject)dm); 1937dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 1938c506a872SMatthew G. Knepley PetscOptionsEnd(); 1939c506a872SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix[0] == '\0' ? NULL : oldPrefix)); 1940c506a872SMatthew G. Knepley } 19419566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 1942a157612eSMichael Lange /* Compute point overlap with neighbouring processes on the distributed DM */ 19439566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Partition, dm, 0, 0, 0)); 19449566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &rootSection)); 19459566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &leafSection)); 19469566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeOwnership(dm, rootSection, &rootrank, leafSection, &leafrank)); 1947c506a872SMatthew 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)); 1948c506a872SMatthew G. Knepley else PetscCall(DMPlexCreateOverlapLabel(dm, overlap, rootSection, rootrank, leafSection, leafrank, &lblOverlap)); 1949a9f1d5b2SMichael Lange /* Convert overlap label to stratified migration SF */ 19509566063dSJacob Faibussowitsch PetscCall(DMPlexPartitionLabelCreateSF(dm, lblOverlap, &sfOverlap)); 19519566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, sfOverlap, &sfStratified)); 19529566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfOverlap)); 1953a9f1d5b2SMichael Lange sfOverlap = sfStratified; 19549566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfOverlap, "Overlap SF")); 19559566063dSJacob Faibussowitsch PetscCall(PetscSFSetFromOptions(sfOverlap)); 1956a9f1d5b2SMichael Lange 19579566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSection)); 19589566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSection)); 19599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rootrank)); 19609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&leafrank)); 19619566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Partition, dm, 0, 0, 0)); 1962a157612eSMichael Lange 1963a157612eSMichael Lange /* Build the overlapping DM */ 19649566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, dmOverlap)); 19659566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*dmOverlap, "Parallel Mesh")); 19669566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(dm, sfOverlap, *dmOverlap)); 1967cb54e036SVaclav Hapla /* Store the overlap in the new DM */ 196860667520SVaclav Hapla PetscCall(DMPlexSetOverlap_Plex(*dmOverlap, dm, overlap)); 1969f5bf2dbfSMichael Lange /* Build the new point SF */ 19709566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*dmOverlap, sfOverlap, PETSC_FALSE, &sfPoint)); 19719566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*dmOverlap, sfPoint)); 19729566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dmOverlap, &dmCoord)); 19739566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 19746858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(*dmOverlap, &dmCoord)); 19756858538eSMatthew G. Knepley if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 19769566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 1977a157612eSMichael Lange /* Cleanup overlap partition */ 19789566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblOverlap)); 1979a9f1d5b2SMichael Lange if (sf) *sf = sfOverlap; 19809566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfOverlap)); 19819566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 19823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1983a157612eSMichael Lange } 19846462276dSToby Isaac 1985d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap_Plex(DM dm, PetscInt *overlap) 1986d71ae5a4SJacob Faibussowitsch { 1987cb54e036SVaclav Hapla DM_Plex *mesh = (DM_Plex *)dm->data; 1988cb54e036SVaclav Hapla 1989cb54e036SVaclav Hapla PetscFunctionBegin; 1990cb54e036SVaclav Hapla *overlap = mesh->overlap; 19913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1992cb54e036SVaclav Hapla } 1993cb54e036SVaclav Hapla 1994d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap_Plex(DM dm, DM dmSrc, PetscInt overlap) 1995d71ae5a4SJacob Faibussowitsch { 199660667520SVaclav Hapla DM_Plex *mesh = NULL; 199760667520SVaclav Hapla DM_Plex *meshSrc = NULL; 199860667520SVaclav Hapla 199960667520SVaclav Hapla PetscFunctionBegin; 200060667520SVaclav Hapla PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 200160667520SVaclav Hapla mesh = (DM_Plex *)dm->data; 200260667520SVaclav Hapla mesh->overlap = overlap; 200360667520SVaclav Hapla if (dmSrc) { 200460667520SVaclav Hapla PetscValidHeaderSpecificType(dmSrc, DM_CLASSID, 2, DMPLEX); 200560667520SVaclav Hapla meshSrc = (DM_Plex *)dmSrc->data; 200660667520SVaclav Hapla mesh->overlap += meshSrc->overlap; 200760667520SVaclav Hapla } 20083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 200960667520SVaclav Hapla } 201060667520SVaclav Hapla 2011cb54e036SVaclav Hapla /*@ 2012c506a872SMatthew G. Knepley DMPlexGetOverlap - Get the width of the cell overlap 2013cb54e036SVaclav Hapla 2014*20f4b53cSBarry Smith Not Collective 2015cb54e036SVaclav Hapla 2016cb54e036SVaclav Hapla Input Parameter: 2017*20f4b53cSBarry Smith . dm - The `DM` 2018cb54e036SVaclav Hapla 2019064ec1f3Sprj- Output Parameter: 2020c506a872SMatthew G. Knepley . overlap - the width of the cell overlap 2021cb54e036SVaclav Hapla 2022cb54e036SVaclav Hapla Level: intermediate 2023cb54e036SVaclav Hapla 2024*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexSetOverlap()`, `DMPlexDistribute()` 2025cb54e036SVaclav Hapla @*/ 2026d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOverlap(DM dm, PetscInt *overlap) 2027d71ae5a4SJacob Faibussowitsch { 2028cb54e036SVaclav Hapla PetscFunctionBegin; 2029cb54e036SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2030c506a872SMatthew G. Knepley PetscValidIntPointer(overlap, 2); 2031cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexGetOverlap_C", (DM, PetscInt *), (dm, overlap)); 20323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2033cb54e036SVaclav Hapla } 2034cb54e036SVaclav Hapla 2035c506a872SMatthew G. Knepley /*@ 2036c506a872SMatthew G. Knepley DMPlexSetOverlap - Set the width of the cell overlap 2037c506a872SMatthew G. Knepley 2038*20f4b53cSBarry Smith Logically Collective 2039c506a872SMatthew G. Knepley 2040c506a872SMatthew G. Knepley Input Parameters: 2041*20f4b53cSBarry Smith + dm - The `DM` 2042*20f4b53cSBarry Smith . dmSrc - The `DM` that produced this one, or `NULL` 2043c506a872SMatthew G. Knepley - overlap - the width of the cell overlap 2044c506a872SMatthew G. Knepley 2045c506a872SMatthew G. Knepley Level: intermediate 2046c506a872SMatthew G. Knepley 2047*20f4b53cSBarry Smith Note: 2048*20f4b53cSBarry Smith The overlap from `dmSrc` is added to `dm` 2049*20f4b53cSBarry Smith 2050*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexGetOverlap()`, `DMPlexDistribute()` 2051c506a872SMatthew G. Knepley @*/ 2052d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOverlap(DM dm, DM dmSrc, PetscInt overlap) 2053d71ae5a4SJacob Faibussowitsch { 2054c506a872SMatthew G. Knepley PetscFunctionBegin; 2055c506a872SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2056c506a872SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 3); 2057c506a872SMatthew G. Knepley PetscTryMethod(dm, "DMPlexSetOverlap_C", (DM, DM, PetscInt), (dm, dmSrc, overlap)); 20583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2059c506a872SMatthew G. Knepley } 2060c506a872SMatthew G. Knepley 2061d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault_Plex(DM dm, PetscBool dist) 2062d71ae5a4SJacob Faibussowitsch { 2063e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2064e600fa54SMatthew G. Knepley 2065e600fa54SMatthew G. Knepley PetscFunctionBegin; 2066e600fa54SMatthew G. Knepley mesh->distDefault = dist; 20673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2068e600fa54SMatthew G. Knepley } 2069e600fa54SMatthew G. Knepley 2070e600fa54SMatthew G. Knepley /*@ 2071*20f4b53cSBarry Smith DMPlexDistributeSetDefault - Set flag indicating whether the `DM` should be distributed by default 2072e600fa54SMatthew G. Knepley 2073*20f4b53cSBarry Smith Logically Collective 2074e600fa54SMatthew G. Knepley 2075e600fa54SMatthew G. Knepley Input Parameters: 2076*20f4b53cSBarry Smith + dm - The `DM` 2077e600fa54SMatthew G. Knepley - dist - Flag for distribution 2078e600fa54SMatthew G. Knepley 2079e600fa54SMatthew G. Knepley Level: intermediate 2080e600fa54SMatthew G. Knepley 2081*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributeGetDefault()`, `DMPlexDistribute()` 2082e600fa54SMatthew G. Knepley @*/ 2083d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeSetDefault(DM dm, PetscBool dist) 2084d71ae5a4SJacob Faibussowitsch { 2085e600fa54SMatthew G. Knepley PetscFunctionBegin; 2086e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2087e600fa54SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, dist, 2); 2088cac4c232SBarry Smith PetscTryMethod(dm, "DMPlexDistributeSetDefault_C", (DM, PetscBool), (dm, dist)); 20893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2090e600fa54SMatthew G. Knepley } 2091e600fa54SMatthew G. Knepley 2092d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault_Plex(DM dm, PetscBool *dist) 2093d71ae5a4SJacob Faibussowitsch { 2094e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2095e600fa54SMatthew G. Knepley 2096e600fa54SMatthew G. Knepley PetscFunctionBegin; 2097e600fa54SMatthew G. Knepley *dist = mesh->distDefault; 20983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2099e600fa54SMatthew G. Knepley } 2100e600fa54SMatthew G. Knepley 2101e600fa54SMatthew G. Knepley /*@ 2102*20f4b53cSBarry Smith DMPlexDistributeGetDefault - Get flag indicating whether the `DM` should be distributed by default 2103e600fa54SMatthew G. Knepley 2104*20f4b53cSBarry Smith Not Collective 2105e600fa54SMatthew G. Knepley 2106e600fa54SMatthew G. Knepley Input Parameter: 2107*20f4b53cSBarry Smith . dm - The `DM` 2108e600fa54SMatthew G. Knepley 2109e600fa54SMatthew G. Knepley Output Parameter: 2110e600fa54SMatthew G. Knepley . dist - Flag for distribution 2111e600fa54SMatthew G. Knepley 2112e600fa54SMatthew G. Knepley Level: intermediate 2113e600fa54SMatthew G. Knepley 2114*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `DMPlexDistributeSetDefault()`, `DMPlexDistribute()` 2115e600fa54SMatthew G. Knepley @*/ 2116d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributeGetDefault(DM dm, PetscBool *dist) 2117d71ae5a4SJacob Faibussowitsch { 2118e600fa54SMatthew G. Knepley PetscFunctionBegin; 2119e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2120e600fa54SMatthew G. Knepley PetscValidBoolPointer(dist, 2); 2121cac4c232SBarry Smith PetscUseMethod(dm, "DMPlexDistributeGetDefault_C", (DM, PetscBool *), (dm, dist)); 21223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2123e600fa54SMatthew G. Knepley } 2124e600fa54SMatthew G. Knepley 21256462276dSToby Isaac /*@C 2126*20f4b53cSBarry Smith DMPlexGetGatherDM - Get a copy of the `DMPLEX` that gathers all points on the 21276462276dSToby Isaac root process of the original's communicator. 21286462276dSToby Isaac 2129*20f4b53cSBarry Smith Collective 213083655b49SVáclav Hapla 2131064ec1f3Sprj- Input Parameter: 2132*20f4b53cSBarry Smith . dm - the original `DMPLEX` object 21336462276dSToby Isaac 21346462276dSToby Isaac Output Parameters: 2135*20f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional) 2136*20f4b53cSBarry Smith - gatherMesh - the gathered `DM` object, or `NULL` 21376462276dSToby Isaac 21386462276dSToby Isaac Level: intermediate 21396462276dSToby Isaac 2140*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DM`, `PetscSF`, `DMPlexDistribute()`, `DMPlexGetRedundantDM()` 21416462276dSToby Isaac @*/ 2142d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetGatherDM(DM dm, PetscSF *sf, DM *gatherMesh) 2143d71ae5a4SJacob Faibussowitsch { 21446462276dSToby Isaac MPI_Comm comm; 21456462276dSToby Isaac PetscMPIInt size; 21466462276dSToby Isaac PetscPartitioner oldPart, gatherPart; 21476462276dSToby Isaac 21486462276dSToby Isaac PetscFunctionBegin; 21496462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2150064a246eSJacob Faibussowitsch PetscValidPointer(gatherMesh, 3); 21510c86c063SLisandro Dalcin *gatherMesh = NULL; 2152a13df41bSStefano Zampini if (sf) *sf = NULL; 21536462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 21549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 21553ba16761SJacob Faibussowitsch if (size == 1) PetscFunctionReturn(PETSC_SUCCESS); 21569566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &oldPart)); 21579566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)oldPart)); 21589566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(comm, &gatherPart)); 21599566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetType(gatherPart, PETSCPARTITIONERGATHER)); 21609566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, gatherPart)); 21619566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, sf, gatherMesh)); 2162a13df41bSStefano Zampini 21639566063dSJacob Faibussowitsch PetscCall(DMPlexSetPartitioner(dm, oldPart)); 21649566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&gatherPart)); 21659566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&oldPart)); 21663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21676462276dSToby Isaac } 21686462276dSToby Isaac 21696462276dSToby Isaac /*@C 2170*20f4b53cSBarry Smith DMPlexGetRedundantDM - Get a copy of the `DMPLEX` that is completely copied on each process. 21716462276dSToby Isaac 2172*20f4b53cSBarry Smith Collective 217383655b49SVáclav Hapla 2174064ec1f3Sprj- Input Parameter: 2175*20f4b53cSBarry Smith . dm - the original `DMPLEX` object 21766462276dSToby Isaac 21776462276dSToby Isaac Output Parameters: 2178*20f4b53cSBarry Smith + sf - the `PetscSF` used for point distribution (optional) 2179*20f4b53cSBarry Smith - redundantMesh - the redundant `DM` object, or `NULL` 21806462276dSToby Isaac 21816462276dSToby Isaac Level: intermediate 21826462276dSToby Isaac 2183*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetGatherDM()` 21846462276dSToby Isaac @*/ 2185d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRedundantDM(DM dm, PetscSF *sf, DM *redundantMesh) 2186d71ae5a4SJacob Faibussowitsch { 21876462276dSToby Isaac MPI_Comm comm; 21886462276dSToby Isaac PetscMPIInt size, rank; 21896462276dSToby Isaac PetscInt pStart, pEnd, p; 21906462276dSToby Isaac PetscInt numPoints = -1; 2191a13df41bSStefano Zampini PetscSF migrationSF, sfPoint, gatherSF; 21926462276dSToby Isaac DM gatherDM, dmCoord; 21936462276dSToby Isaac PetscSFNode *points; 21946462276dSToby Isaac 21956462276dSToby Isaac PetscFunctionBegin; 21966462276dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2197064a246eSJacob Faibussowitsch PetscValidPointer(redundantMesh, 3); 21980c86c063SLisandro Dalcin *redundantMesh = NULL; 21996462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 22009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 220168dbc166SMatthew G. Knepley if (size == 1) { 22029566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 220368dbc166SMatthew G. Knepley *redundantMesh = dm; 2204a13df41bSStefano Zampini if (sf) *sf = NULL; 22053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 220668dbc166SMatthew G. Knepley } 22079566063dSJacob Faibussowitsch PetscCall(DMPlexGetGatherDM(dm, &gatherSF, &gatherDM)); 22083ba16761SJacob Faibussowitsch if (!gatherDM) PetscFunctionReturn(PETSC_SUCCESS); 22099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 22109566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(gatherDM, &pStart, &pEnd)); 22116462276dSToby Isaac numPoints = pEnd - pStart; 22129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&numPoints, 1, MPIU_INT, 0, comm)); 22139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &points)); 22149566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &migrationSF)); 22156462276dSToby Isaac for (p = 0; p < numPoints; p++) { 22166462276dSToby Isaac points[p].index = p; 22176462276dSToby Isaac points[p].rank = 0; 22186462276dSToby Isaac } 22199566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(migrationSF, pEnd - pStart, numPoints, NULL, PETSC_OWN_POINTER, points, PETSC_OWN_POINTER)); 22209566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(comm, redundantMesh)); 22219566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*redundantMesh, "Redundant Mesh")); 22229566063dSJacob Faibussowitsch PetscCall(DMPlexMigrate(gatherDM, migrationSF, *redundantMesh)); 22232e28cf0cSVaclav Hapla /* This is to express that all point are in overlap */ 22242e28cf0cSVaclav Hapla PetscCall(DMPlexSetOverlap_Plex(*redundantMesh, NULL, PETSC_MAX_INT)); 22259566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointSF(*redundantMesh, migrationSF, PETSC_FALSE, &sfPoint)); 22269566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(*redundantMesh, sfPoint)); 22279566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*redundantMesh, &dmCoord)); 22289566063dSJacob Faibussowitsch if (dmCoord) PetscCall(DMSetPointSF(dmCoord, sfPoint)); 22299566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 2230a13df41bSStefano Zampini if (sf) { 2231a13df41bSStefano Zampini PetscSF tsf; 2232a13df41bSStefano Zampini 22339566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(gatherSF, migrationSF, &tsf)); 22349566063dSJacob Faibussowitsch PetscCall(DMPlexStratifyMigrationSF(dm, tsf, sf)); 22359566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&tsf)); 2236a13df41bSStefano Zampini } 22379566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&migrationSF)); 22389566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&gatherSF)); 22399566063dSJacob Faibussowitsch PetscCall(DMDestroy(&gatherDM)); 22409566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *redundantMesh)); 22415de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, *redundantMesh)); 22423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22436462276dSToby Isaac } 22445fa78c88SVaclav Hapla 22455fa78c88SVaclav Hapla /*@ 2246*20f4b53cSBarry Smith DMPlexIsDistributed - Find out whether this `DM` is distributed, i.e. more than one rank owns some points. 22475fa78c88SVaclav Hapla 22485fa78c88SVaclav Hapla Collective 22495fa78c88SVaclav Hapla 22505fa78c88SVaclav Hapla Input Parameter: 2251*20f4b53cSBarry Smith . dm - The `DM` object 22525fa78c88SVaclav Hapla 22535fa78c88SVaclav Hapla Output Parameter: 2254*20f4b53cSBarry Smith . distributed - Flag whether the `DM` is distributed 22555fa78c88SVaclav Hapla 22565fa78c88SVaclav Hapla Level: intermediate 22575fa78c88SVaclav Hapla 22585fa78c88SVaclav Hapla Notes: 22595fa78c88SVaclav Hapla This currently finds out whether at least two ranks have any DAG points. 2260*20f4b53cSBarry Smith This involves `MPI_Allreduce()` with one integer. 22615fa78c88SVaclav Hapla The result is currently not stashed so every call to this routine involves this global communication. 22625fa78c88SVaclav Hapla 2263*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPLEX`, `DMPlexDistribute()`, `DMPlexGetOverlap()`, `DMPlexIsInterpolated()` 22645fa78c88SVaclav Hapla @*/ 2265d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsDistributed(DM dm, PetscBool *distributed) 2266d71ae5a4SJacob Faibussowitsch { 22675fa78c88SVaclav Hapla PetscInt pStart, pEnd, count; 22685fa78c88SVaclav Hapla MPI_Comm comm; 226935d70e31SStefano Zampini PetscMPIInt size; 22705fa78c88SVaclav Hapla 22715fa78c88SVaclav Hapla PetscFunctionBegin; 22725fa78c88SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2273dadcf809SJacob Faibussowitsch PetscValidBoolPointer(distributed, 2); 22749566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 22759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 22769371c9d4SSatish Balay if (size == 1) { 22779371c9d4SSatish Balay *distributed = PETSC_FALSE; 22783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22799371c9d4SSatish Balay } 22809566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 228135d70e31SStefano Zampini count = (pEnd - pStart) > 0 ? 1 : 0; 22829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &count, 1, MPIU_INT, MPI_SUM, comm)); 22835fa78c88SVaclav Hapla *distributed = count > 1 ? PETSC_TRUE : PETSC_FALSE; 22843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22855fa78c88SVaclav Hapla } 22861d1f2f2aSksagiyam 22871d1f2f2aSksagiyam /*@C 22881d1f2f2aSksagiyam DMPlexDistributionSetName - Set the name of the specific parallel distribution 22891d1f2f2aSksagiyam 22901d1f2f2aSksagiyam Input Parameters: 2291*20f4b53cSBarry Smith + dm - The `DM` 22921d1f2f2aSksagiyam - name - The name of the specific parallel distribution 22931d1f2f2aSksagiyam 22941d1f2f2aSksagiyam Level: developer 22951d1f2f2aSksagiyam 2296*20f4b53cSBarry Smith Note: 2297*20f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's 2298*20f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under 2299*20f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()` 2300*20f4b53cSBarry Smith loads the parallel distribution stored in file under this name. 2301*20f4b53cSBarry Smith 2302*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionGetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()` 23031d1f2f2aSksagiyam @*/ 2304d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionSetName(DM dm, const char name[]) 2305d71ae5a4SJacob Faibussowitsch { 23061d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data; 23071d1f2f2aSksagiyam 23081d1f2f2aSksagiyam PetscFunctionBegin; 23091d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 23101d1f2f2aSksagiyam if (name) PetscValidCharPointer(name, 2); 23111d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 23121d1f2f2aSksagiyam PetscCall(PetscStrallocpy(name, &mesh->distributionName)); 23133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23141d1f2f2aSksagiyam } 23151d1f2f2aSksagiyam 23161d1f2f2aSksagiyam /*@C 23171d1f2f2aSksagiyam DMPlexDistributionGetName - Retrieve the name of the specific parallel distribution 23181d1f2f2aSksagiyam 23191d1f2f2aSksagiyam Input Parameter: 2320*20f4b53cSBarry Smith . dm - The `DM` 23211d1f2f2aSksagiyam 23221d1f2f2aSksagiyam Output Parameter: 23231d1f2f2aSksagiyam . name - The name of the specific parallel distribution 23241d1f2f2aSksagiyam 23251d1f2f2aSksagiyam Level: developer 23261d1f2f2aSksagiyam 2327*20f4b53cSBarry Smith Note: 2328*20f4b53cSBarry Smith If distribution name is set when saving, `DMPlexTopologyView()` saves the plex's 2329*20f4b53cSBarry Smith parallel distribution (i.e., partition, ownership, and local ordering of points) under 2330*20f4b53cSBarry Smith this name. Conversely, if distribution name is set when loading, `DMPlexTopologyLoad()` 2331*20f4b53cSBarry Smith loads the parallel distribution stored in file under this name. 2332*20f4b53cSBarry Smith 2333*20f4b53cSBarry Smith .seealso: `DMPLEX`, `DMPlexDistributionSetName()`, `DMPlexTopologyView()`, `DMPlexTopologyLoad()` 23341d1f2f2aSksagiyam @*/ 2335d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexDistributionGetName(DM dm, const char *name[]) 2336d71ae5a4SJacob Faibussowitsch { 23371d1f2f2aSksagiyam DM_Plex *mesh = (DM_Plex *)dm->data; 23381d1f2f2aSksagiyam 23391d1f2f2aSksagiyam PetscFunctionBegin; 23401d1f2f2aSksagiyam PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 23411d1f2f2aSksagiyam PetscValidPointer(name, 2); 23421d1f2f2aSksagiyam *name = mesh->distributionName; 23433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23441d1f2f2aSksagiyam } 2345