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 93c1f0c11SLawrence Mitchell . user - The user callback, may be NULL (to clear the callback) 103c1f0c11SLawrence Mitchell - ctx - context for callback evaluation, may be NULL 113c1f0c11SLawrence Mitchell 123c1f0c11SLawrence Mitchell Level: advanced 133c1f0c11SLawrence Mitchell 143c1f0c11SLawrence Mitchell Notes: 153c1f0c11SLawrence Mitchell The caller of DMPlexGetAdjacency may need to arrange that a large enough array is available for the adjacency. 163c1f0c11SLawrence Mitchell 173c1f0c11SLawrence Mitchell Any setting here overrides other configuration of DMPlex adjacency determination. 183c1f0c11SLawrence Mitchell 19b0441da4SMatthew G. Knepley .seealso: DMSetAdjacency(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexGetAdjacency(), DMPlexGetAdjacencyUser() 203c1f0c11SLawrence Mitchell @*/ 213c1f0c11SLawrence Mitchell PetscErrorCode DMPlexSetAdjacencyUser(DM dm,PetscErrorCode (*user)(DM,PetscInt,PetscInt*,PetscInt[],void*),void *ctx) 223c1f0c11SLawrence Mitchell { 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; 293c1f0c11SLawrence Mitchell PetscFunctionReturn(0); 303c1f0c11SLawrence Mitchell } 313c1f0c11SLawrence Mitchell 323c1f0c11SLawrence Mitchell /*@C 333c1f0c11SLawrence Mitchell DMPlexGetAdjacencyUser - get the user-defined adjacency callback 343c1f0c11SLawrence Mitchell 353c1f0c11SLawrence Mitchell Input Parameter: 363c1f0c11SLawrence Mitchell . dm - The DM object 373c1f0c11SLawrence Mitchell 383c1f0c11SLawrence Mitchell Output Parameters: 396b867d5aSJose E. Roman + user - The user callback 403c1f0c11SLawrence Mitchell - ctx - context for callback evaluation 413c1f0c11SLawrence Mitchell 423c1f0c11SLawrence Mitchell Level: advanced 433c1f0c11SLawrence Mitchell 44b0441da4SMatthew G. Knepley .seealso: DMSetAdjacency(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexGetAdjacency(), DMPlexSetAdjacencyUser() 453c1f0c11SLawrence Mitchell @*/ 463c1f0c11SLawrence Mitchell PetscErrorCode DMPlexGetAdjacencyUser(DM dm, PetscErrorCode (**user)(DM,PetscInt,PetscInt*,PetscInt[],void*), void **ctx) 473c1f0c11SLawrence Mitchell { 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; 543c1f0c11SLawrence Mitchell PetscFunctionReturn(0); 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: 618b0b4c70SToby Isaac + 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 66b0441da4SMatthew G. Knepley .seealso: DMGetAdjacency(), DMSetAdjacency(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexSetAnchors() 678b0b4c70SToby Isaac @*/ 685b317d89SToby Isaac PetscErrorCode DMPlexSetAdjacencyUseAnchors(DM dm, PetscBool useAnchors) 698b0b4c70SToby Isaac { 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; 758b0b4c70SToby Isaac PetscFunctionReturn(0); 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: 828b0b4c70SToby Isaac . 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 89b0441da4SMatthew G. Knepley .seealso: DMPlexSetAdjacencyUseAnchors(), DMSetAdjacency(), DMGetAdjacency(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexSetAnchors() 908b0b4c70SToby Isaac @*/ 915b317d89SToby Isaac PetscErrorCode DMPlexGetAdjacencyUseAnchors(DM dm, PetscBool *useAnchors) 928b0b4c70SToby Isaac { 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; 998b0b4c70SToby Isaac PetscFunctionReturn(0); 1008b0b4c70SToby Isaac } 1018b0b4c70SToby Isaac 10270034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Cone_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[]) 10370034214SMatthew G. Knepley { 10470034214SMatthew G. Knepley const PetscInt *cone = NULL; 10570034214SMatthew G. Knepley PetscInt numAdj = 0, maxAdjSize = *adjSize, coneSize, c; 10670034214SMatthew G. Knepley 10770034214SMatthew G. Knepley PetscFunctionBeginHot; 1085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize)); 1095f80ce2aSJacob Faibussowitsch CHKERRQ(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 1155f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, point, &supportSize)); 1165f80ce2aSJacob Faibussowitsch CHKERRQ(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 } 1212c71b3e2SJacob Faibussowitsch PetscCheckFalse(numAdj > maxAdjSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 12270034214SMatthew G. Knepley } 12370034214SMatthew G. Knepley } 12470034214SMatthew G. Knepley *adjSize = numAdj; 12570034214SMatthew G. Knepley PetscFunctionReturn(0); 12670034214SMatthew G. Knepley } 12770034214SMatthew G. Knepley 12870034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Support_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[]) 12970034214SMatthew G. Knepley { 13070034214SMatthew G. Knepley const PetscInt *support = NULL; 13170034214SMatthew G. Knepley PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 13270034214SMatthew G. Knepley 13370034214SMatthew G. Knepley PetscFunctionBeginHot; 1345f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetSupportSize(dm, p, &supportSize)); 1355f80ce2aSJacob Faibussowitsch CHKERRQ(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 1415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSize(dm, point, &coneSize)); 1425f80ce2aSJacob Faibussowitsch CHKERRQ(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 } 1472c71b3e2SJacob Faibussowitsch PetscCheckFalse(numAdj > maxAdjSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 14870034214SMatthew G. Knepley } 14970034214SMatthew G. Knepley } 15070034214SMatthew G. Knepley *adjSize = numAdj; 15170034214SMatthew G. Knepley PetscFunctionReturn(0); 15270034214SMatthew G. Knepley } 15370034214SMatthew G. Knepley 15470034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Transitive_Internal(DM dm, PetscInt p, PetscBool useClosure, PetscInt *adjSize, PetscInt adj[]) 15570034214SMatthew G. Knepley { 15670034214SMatthew G. Knepley PetscInt *star = NULL; 15770034214SMatthew G. Knepley PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 15870034214SMatthew G. Knepley 15970034214SMatthew G. Knepley PetscFunctionBeginHot; 1605f80ce2aSJacob Faibussowitsch CHKERRQ(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 1655f80ce2aSJacob Faibussowitsch CHKERRQ(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 } 1702c71b3e2SJacob Faibussowitsch PetscCheckFalse(numAdj > maxAdjSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 17170034214SMatthew G. Knepley } 1725f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure)); 17370034214SMatthew G. Knepley } 1745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexRestoreTransitiveClosure(dm, p, useClosure, &starSize, &star)); 17570034214SMatthew G. Knepley *adjSize = numAdj; 17670034214SMatthew G. Knepley PetscFunctionReturn(0); 17770034214SMatthew G. Knepley } 17870034214SMatthew G. Knepley 1795b317d89SToby Isaac PetscErrorCode DMPlexGetAdjacency_Internal(DM dm, PetscInt p, PetscBool useCone, PetscBool useTransitiveClosure, PetscBool useAnchors, PetscInt *adjSize, PetscInt *adj[]) 18070034214SMatthew G. Knepley { 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) { 1925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAnchors(dm,&aSec,&aIS)); 1938b0b4c70SToby Isaac if (aSec) { 1945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetMaxDof(aSec,&maxAnchors)); 19524c766afSToby Isaac maxAnchors = PetscMax(1,maxAnchors); 1965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(aSec,&aStart,&aEnd)); 1975f80ce2aSJacob Faibussowitsch CHKERRQ(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 2035f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart,&pEnd)); 2045f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 205412e9a14SMatthew G. Knepley depth = PetscMax(depth, -depth); 2065f80ce2aSJacob Faibussowitsch CHKERRQ(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); 2125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(asiz,adj)); 21379bad331SMatthew G. Knepley } 21479bad331SMatthew G. Knepley if (*adjSize < 0) *adjSize = asiz; 2158b0b4c70SToby Isaac maxAdjSize = *adjSize; 2163c1f0c11SLawrence Mitchell if (mesh->useradjacency) { 2175f80ce2aSJacob Faibussowitsch CHKERRQ((*mesh->useradjacency)(dm, p, adjSize, *adj, mesh->useradjacencyctx)); 2183c1f0c11SLawrence Mitchell } else if (useTransitiveClosure) { 2195f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency_Transitive_Internal(dm, p, useCone, adjSize, *adj)); 22070034214SMatthew G. Knepley } else if (useCone) { 2215f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency_Cone_Internal(dm, p, adjSize, *adj)); 22270034214SMatthew G. Knepley } else { 2235f80ce2aSJacob Faibussowitsch CHKERRQ(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 2358b0b4c70SToby Isaac if (p >= aStart && p < aEnd) { 2365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(aSec,p,&aDof)); 2378b0b4c70SToby Isaac } 2388b0b4c70SToby Isaac if (aDof) { 2398b0b4c70SToby Isaac PetscInt aOff; 2408b0b4c70SToby Isaac PetscInt s, q; 2418b0b4c70SToby Isaac 2428b0b4c70SToby Isaac for (j = i + 1; j < numAdj; j++) { 2438b0b4c70SToby Isaac orig[j - 1] = orig[j]; 2448b0b4c70SToby Isaac } 2458b0b4c70SToby Isaac origSize--; 2468b0b4c70SToby Isaac numAdj--; 2475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(aSec,p,&aOff)); 2488b0b4c70SToby Isaac for (s = 0; s < aDof; ++s) { 249527e7439SSatish Balay for (q = 0; q < numAdj || ((void)(orig[numAdj++] = anchors[aOff+s]),0); ++q) { 2508b0b4c70SToby Isaac if (anchors[aOff+s] == orig[q]) break; 2518b0b4c70SToby Isaac } 2522c71b3e2SJacob Faibussowitsch PetscCheckFalse(numAdj > maxAdjSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 2538b0b4c70SToby Isaac } 2548b0b4c70SToby Isaac } 2558b0b4c70SToby Isaac else { 2568b0b4c70SToby Isaac i++; 2578b0b4c70SToby Isaac } 2588b0b4c70SToby Isaac } 2598b0b4c70SToby Isaac *adjSize = numAdj; 2605f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(aIS,&anchors)); 2618b0b4c70SToby Isaac } 26270034214SMatthew G. Knepley PetscFunctionReturn(0); 26370034214SMatthew G. Knepley } 26470034214SMatthew G. Knepley 26570034214SMatthew G. Knepley /*@ 26670034214SMatthew G. Knepley DMPlexGetAdjacency - Return all points adjacent to the given point 26770034214SMatthew G. Knepley 26870034214SMatthew G. Knepley Input Parameters: 26970034214SMatthew G. Knepley + dm - The DM object 2706b867d5aSJose E. Roman - p - The point 27170034214SMatthew G. Knepley 2726b867d5aSJose E. Roman Input/Output Parameters: 2736b867d5aSJose E. Roman + adjSize - The maximum size of adj if it is non-NULL, or PETSC_DETERMINE; 2746b867d5aSJose E. Roman on output the number of adjacent points 2756b867d5aSJose E. Roman - adj - Either NULL so that the array is allocated, or an existing array with size adjSize; 2766b867d5aSJose E. Roman on output contains the adjacent points 27770034214SMatthew G. Knepley 27870034214SMatthew G. Knepley Level: advanced 27970034214SMatthew G. Knepley 28095452b02SPatrick Sanan Notes: 28195452b02SPatrick Sanan The user must PetscFree the adj array if it was not passed in. 28270034214SMatthew G. Knepley 283b0441da4SMatthew G. Knepley .seealso: DMSetAdjacency(), DMPlexDistribute(), DMCreateMatrix(), DMPlexPreallocateOperator() 28470034214SMatthew G. Knepley @*/ 28570034214SMatthew G. Knepley PetscErrorCode DMPlexGetAdjacency(DM dm, PetscInt p, PetscInt *adjSize, PetscInt *adj[]) 28670034214SMatthew G. Knepley { 2871cf84007SMatthew G. Knepley PetscBool useCone, useClosure, useAnchors; 28870034214SMatthew G. Knepley 28970034214SMatthew G. Knepley PetscFunctionBeginHot; 29070034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29170034214SMatthew G. Knepley PetscValidPointer(adjSize,3); 29270034214SMatthew G. Knepley PetscValidPointer(adj,4); 2935f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 2945f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors)); 2955f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency_Internal(dm, p, useCone, useClosure, useAnchors, adjSize, adj)); 29670034214SMatthew G. Knepley PetscFunctionReturn(0); 29770034214SMatthew G. Knepley } 29808633170SToby Isaac 299b0a623aaSMatthew G. Knepley /*@ 300b0a623aaSMatthew G. Knepley DMPlexCreateTwoSidedProcessSF - Create an SF which just has process connectivity 301b0a623aaSMatthew G. Knepley 302d083f849SBarry Smith Collective on dm 303b0a623aaSMatthew G. Knepley 304b0a623aaSMatthew G. Knepley Input Parameters: 305b0a623aaSMatthew G. Knepley + dm - The DM 3066b867d5aSJose E. Roman . sfPoint - The PetscSF which encodes point connectivity 3076b867d5aSJose E. Roman . rootRankSection - 3086b867d5aSJose E. Roman . rootRanks - 3096b867d5aSJose E. Roman . leftRankSection - 3106b867d5aSJose E. Roman - leafRanks - 311b0a623aaSMatthew G. Knepley 312b0a623aaSMatthew G. Knepley Output Parameters: 313b0a623aaSMatthew G. Knepley + processRanks - A list of process neighbors, or NULL 314b0a623aaSMatthew G. Knepley - sfProcess - An SF encoding the two-sided process connectivity, or NULL 315b0a623aaSMatthew G. Knepley 316b0a623aaSMatthew G. Knepley Level: developer 317b0a623aaSMatthew G. Knepley 318b0a623aaSMatthew G. Knepley .seealso: PetscSFCreate(), DMPlexCreateProcessSF() 319b0a623aaSMatthew G. Knepley @*/ 320b0a623aaSMatthew G. Knepley PetscErrorCode DMPlexCreateTwoSidedProcessSF(DM dm, PetscSF sfPoint, PetscSection rootRankSection, IS rootRanks, PetscSection leafRankSection, IS leafRanks, IS *processRanks, PetscSF *sfProcess) 321b0a623aaSMatthew G. Knepley { 322b0a623aaSMatthew G. Knepley const PetscSFNode *remotePoints; 323b0a623aaSMatthew G. Knepley PetscInt *localPointsNew; 324b0a623aaSMatthew G. Knepley PetscSFNode *remotePointsNew; 325b0a623aaSMatthew G. Knepley const PetscInt *nranks; 326b0a623aaSMatthew G. Knepley PetscInt *ranksNew; 327b0a623aaSMatthew G. Knepley PetscBT neighbors; 328b0a623aaSMatthew G. Knepley PetscInt pStart, pEnd, p, numLeaves, l, numNeighbors, n; 3299852e123SBarry Smith PetscMPIInt size, proc, rank; 330b0a623aaSMatthew G. Knepley 331b0a623aaSMatthew G. Knepley PetscFunctionBegin; 332b0a623aaSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 333b0a623aaSMatthew G. Knepley PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2); 334064a246eSJacob Faibussowitsch if (processRanks) {PetscValidPointer(processRanks, 7);} 335064a246eSJacob Faibussowitsch if (sfProcess) {PetscValidPointer(sfProcess, 8);} 3365f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size)); 3375f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 3385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sfPoint, NULL, &numLeaves, NULL, &remotePoints)); 3395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTCreate(size, &neighbors)); 3405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTMemzero(size, neighbors)); 341b0a623aaSMatthew G. Knepley /* Compute root-to-leaf process connectivity */ 3425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(rootRankSection, &pStart, &pEnd)); 3435f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(rootRanks, &nranks)); 344b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 345b0a623aaSMatthew G. Knepley PetscInt ndof, noff, n; 346b0a623aaSMatthew G. Knepley 3475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(rootRankSection, p, &ndof)); 3485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(rootRankSection, p, &noff)); 3495f80ce2aSJacob Faibussowitsch for (n = 0; n < ndof; ++n) CHKERRQ(PetscBTSet(neighbors, nranks[noff+n])); 350b0a623aaSMatthew G. Knepley } 3515f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(rootRanks, &nranks)); 352b0a623aaSMatthew G. Knepley /* Compute leaf-to-neighbor process connectivity */ 3535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(leafRankSection, &pStart, &pEnd)); 3545f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(leafRanks, &nranks)); 355b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 356b0a623aaSMatthew G. Knepley PetscInt ndof, noff, n; 357b0a623aaSMatthew G. Knepley 3585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(leafRankSection, p, &ndof)); 3595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(leafRankSection, p, &noff)); 3605f80ce2aSJacob Faibussowitsch for (n = 0; n < ndof; ++n) CHKERRQ(PetscBTSet(neighbors, nranks[noff+n])); 361b0a623aaSMatthew G. Knepley } 3625f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(leafRanks, &nranks)); 363b0a623aaSMatthew G. Knepley /* Compute leaf-to-root process connectivity */ 364b0a623aaSMatthew G. Knepley for (l = 0; l < numLeaves; ++l) {PetscBTSet(neighbors, remotePoints[l].rank);} 365b0a623aaSMatthew G. Knepley /* Calculate edges */ 366b0a623aaSMatthew G. Knepley PetscBTClear(neighbors, rank); 3679852e123SBarry Smith for (proc = 0, numNeighbors = 0; proc < size; ++proc) {if (PetscBTLookup(neighbors, proc)) ++numNeighbors;} 3685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numNeighbors, &ranksNew)); 3695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numNeighbors, &localPointsNew)); 3705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numNeighbors, &remotePointsNew)); 3719852e123SBarry Smith for (proc = 0, n = 0; proc < size; ++proc) { 372b0a623aaSMatthew G. Knepley if (PetscBTLookup(neighbors, proc)) { 373b0a623aaSMatthew G. Knepley ranksNew[n] = proc; 374b0a623aaSMatthew G. Knepley localPointsNew[n] = proc; 375b0a623aaSMatthew G. Knepley remotePointsNew[n].index = rank; 376b0a623aaSMatthew G. Knepley remotePointsNew[n].rank = proc; 377b0a623aaSMatthew G. Knepley ++n; 378b0a623aaSMatthew G. Knepley } 379b0a623aaSMatthew G. Knepley } 3805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBTDestroy(&neighbors)); 3815f80ce2aSJacob Faibussowitsch if (processRanks) CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)dm), numNeighbors, ranksNew, PETSC_OWN_POINTER, processRanks)); 3825f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscFree(ranksNew)); 383b0a623aaSMatthew G. Knepley if (sfProcess) { 3845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess)); 3855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) *sfProcess, "Two-Sided Process SF")); 3865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetFromOptions(*sfProcess)); 3875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraph(*sfProcess, size, numNeighbors, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER)); 388b0a623aaSMatthew G. Knepley } 389b0a623aaSMatthew G. Knepley PetscFunctionReturn(0); 390b0a623aaSMatthew G. Knepley } 391b0a623aaSMatthew G. Knepley 392b0a623aaSMatthew G. Knepley /*@ 393b0a623aaSMatthew G. Knepley DMPlexDistributeOwnership - Compute owner information for shared points. This basically gets two-sided for an SF. 394b0a623aaSMatthew G. Knepley 395d083f849SBarry Smith Collective on dm 396b0a623aaSMatthew G. Knepley 397b0a623aaSMatthew G. Knepley Input Parameter: 398b0a623aaSMatthew G. Knepley . dm - The DM 399b0a623aaSMatthew G. Knepley 400b0a623aaSMatthew G. Knepley Output Parameters: 401b0a623aaSMatthew G. Knepley + rootSection - The number of leaves for a given root point 402b0a623aaSMatthew G. Knepley . rootrank - The rank of each edge into the root point 403b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point 404b0a623aaSMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point 405b0a623aaSMatthew G. Knepley 406b0a623aaSMatthew G. Knepley Level: developer 407b0a623aaSMatthew G. Knepley 408dccdeccaSVaclav Hapla .seealso: DMPlexCreateOverlapLabel(), DMPlexDistribute(), DMPlexDistributeOverlap() 409b0a623aaSMatthew G. Knepley @*/ 410b0a623aaSMatthew G. Knepley PetscErrorCode DMPlexDistributeOwnership(DM dm, PetscSection rootSection, IS *rootrank, PetscSection leafSection, IS *leafrank) 411b0a623aaSMatthew G. Knepley { 412b0a623aaSMatthew G. Knepley MPI_Comm comm; 413b0a623aaSMatthew G. Knepley PetscSF sfPoint; 414b0a623aaSMatthew G. Knepley const PetscInt *rootdegree; 415b0a623aaSMatthew G. Knepley PetscInt *myrank, *remoterank; 416b0a623aaSMatthew G. Knepley PetscInt pStart, pEnd, p, nedges; 417b0a623aaSMatthew G. Knepley PetscMPIInt rank; 418b0a623aaSMatthew G. Knepley 419b0a623aaSMatthew G. Knepley PetscFunctionBegin; 4205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 4215f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 4225f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 4235f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sfPoint)); 424b0a623aaSMatthew G. Knepley /* Compute number of leaves for each root */ 4255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) rootSection, "Root Section")); 4265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(rootSection, pStart, pEnd)); 4275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeBegin(sfPoint, &rootdegree)); 4285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFComputeDegreeEnd(sfPoint, &rootdegree)); 4295f80ce2aSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) CHKERRQ(PetscSectionSetDof(rootSection, p, rootdegree[p-pStart])); 4305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetUp(rootSection)); 431b0a623aaSMatthew G. Knepley /* Gather rank of each leaf to root */ 4325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(rootSection, &nedges)); 4335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(pEnd-pStart, &myrank)); 4345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nedges, &remoterank)); 435b0a623aaSMatthew G. Knepley for (p = 0; p < pEnd-pStart; ++p) myrank[p] = rank; 4365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGatherBegin(sfPoint, MPIU_INT, myrank, remoterank)); 4375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGatherEnd(sfPoint, MPIU_INT, myrank, remoterank)); 4385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(myrank)); 4395f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm, nedges, remoterank, PETSC_OWN_POINTER, rootrank)); 440b0a623aaSMatthew G. Knepley /* Distribute remote ranks to leaves */ 4415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) leafSection, "Leaf Section")); 4425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeFieldIS(dm, sfPoint, rootSection, *rootrank, leafSection, leafrank)); 443b0a623aaSMatthew G. Knepley PetscFunctionReturn(0); 444b0a623aaSMatthew G. Knepley } 445b0a623aaSMatthew G. Knepley 446278397a0SMatthew G. Knepley /*@C 447dccdeccaSVaclav Hapla DMPlexCreateOverlapLabel - Compute owner information for shared points. This basically gets two-sided for an SF. 448b0a623aaSMatthew G. Knepley 449d083f849SBarry Smith Collective on dm 450b0a623aaSMatthew G. Knepley 451b0a623aaSMatthew G. Knepley Input Parameters: 452b0a623aaSMatthew G. Knepley + dm - The DM 45324d039d7SMichael Lange . levels - Number of overlap levels 454b0a623aaSMatthew G. Knepley . rootSection - The number of leaves for a given root point 455b0a623aaSMatthew G. Knepley . rootrank - The rank of each edge into the root point 456b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point 457b0a623aaSMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point 458b0a623aaSMatthew G. Knepley 459064ec1f3Sprj- Output Parameter: 460b4ec6ac8SBarry Smith . ovLabel - DMLabel containing remote overlap contributions as point/rank pairings 461b0a623aaSMatthew G. Knepley 462b0a623aaSMatthew G. Knepley Level: developer 463b0a623aaSMatthew G. Knepley 4641fd9873aSMichael Lange .seealso: DMPlexDistributeOwnership(), DMPlexDistribute() 465b0a623aaSMatthew G. Knepley @*/ 466dccdeccaSVaclav Hapla PetscErrorCode DMPlexCreateOverlapLabel(DM dm, PetscInt levels, PetscSection rootSection, IS rootrank, PetscSection leafSection, IS leafrank, DMLabel *ovLabel) 467b0a623aaSMatthew G. Knepley { 468e540f424SMichael Lange MPI_Comm comm; 469b0a623aaSMatthew G. Knepley DMLabel ovAdjByRank; /* A DMLabel containing all points adjacent to shared points, separated by rank (value in label) */ 470874ddda9SLisandro Dalcin PetscSF sfPoint; 471b0a623aaSMatthew G. Knepley const PetscSFNode *remote; 472b0a623aaSMatthew G. Knepley const PetscInt *local; 4731fd9873aSMichael Lange const PetscInt *nrank, *rrank; 474b0a623aaSMatthew G. Knepley PetscInt *adj = NULL; 4751fd9873aSMichael Lange PetscInt pStart, pEnd, p, sStart, sEnd, nleaves, l; 4769852e123SBarry Smith PetscMPIInt rank, size; 47731bc6364SLisandro Dalcin PetscBool flg; 478b0a623aaSMatthew G. Knepley 479b0a623aaSMatthew G. Knepley PetscFunctionBegin; 4806ba1a4c7SVaclav Hapla *ovLabel = NULL; 4815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 4825f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 4835f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 4846ba1a4c7SVaclav Hapla if (size == 1) PetscFunctionReturn(0); 4855f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sfPoint)); 4865f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 487d1674c6dSMatthew Knepley if (!levels) { 488d1674c6dSMatthew Knepley /* Add owned points */ 4895f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel)); 4905f80ce2aSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) CHKERRQ(DMLabelSetValue(*ovLabel, p, rank)); 491d1674c6dSMatthew Knepley PetscFunctionReturn(0); 492d1674c6dSMatthew Knepley } 4935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(leafSection, &sStart, &sEnd)); 4945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote)); 4955f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelCreate(PETSC_COMM_SELF, "Overlap adjacency", &ovAdjByRank)); 496b0a623aaSMatthew G. Knepley /* Handle leaves: shared with the root point */ 497b0a623aaSMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 498b0a623aaSMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a; 499b0a623aaSMatthew G. Knepley 5005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency(dm, local ? local[l] : l, &adjSize, &adj)); 5015f80ce2aSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) CHKERRQ(DMLabelSetValue(ovAdjByRank, adj[a], remote[l].rank)); 502b0a623aaSMatthew G. Knepley } 5035f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(rootrank, &rrank)); 5045f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(leafrank, &nrank)); 505b0a623aaSMatthew G. Knepley /* Handle roots */ 506b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 507b0a623aaSMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, neighbors = 0, noff, n, a; 508b0a623aaSMatthew G. Knepley 509b0a623aaSMatthew G. Knepley if ((p >= sStart) && (p < sEnd)) { 510b0a623aaSMatthew G. Knepley /* Some leaves share a root with other leaves on different processes */ 5115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(leafSection, p, &neighbors)); 512b0a623aaSMatthew G. Knepley if (neighbors) { 5135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(leafSection, p, &noff)); 5145f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 515b0a623aaSMatthew G. Knepley for (n = 0; n < neighbors; ++n) { 516b0a623aaSMatthew G. Knepley const PetscInt remoteRank = nrank[noff+n]; 517b0a623aaSMatthew G. Knepley 518b0a623aaSMatthew G. Knepley if (remoteRank == rank) continue; 5195f80ce2aSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) CHKERRQ(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 520b0a623aaSMatthew G. Knepley } 521b0a623aaSMatthew G. Knepley } 522b0a623aaSMatthew G. Knepley } 523b0a623aaSMatthew G. Knepley /* Roots are shared with leaves */ 5245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(rootSection, p, &neighbors)); 525b0a623aaSMatthew G. Knepley if (!neighbors) continue; 5265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(rootSection, p, &noff)); 5275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 528b0a623aaSMatthew G. Knepley for (n = 0; n < neighbors; ++n) { 529b0a623aaSMatthew G. Knepley const PetscInt remoteRank = rrank[noff+n]; 530b0a623aaSMatthew G. Knepley 531b0a623aaSMatthew G. Knepley if (remoteRank == rank) continue; 5325f80ce2aSJacob Faibussowitsch for (a = 0; a < adjSize; ++a) CHKERRQ(DMLabelSetValue(ovAdjByRank, adj[a], remoteRank)); 533b0a623aaSMatthew G. Knepley } 534b0a623aaSMatthew G. Knepley } 5355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(adj)); 5365f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(rootrank, &rrank)); 5375f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(leafrank, &nrank)); 53824d039d7SMichael Lange /* Add additional overlap levels */ 539be200f8dSMichael Lange for (l = 1; l < levels; l++) { 540be200f8dSMichael Lange /* Propagate point donations over SF to capture remote connections */ 5415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPartitionLabelPropagate(dm, ovAdjByRank)); 542be200f8dSMichael Lange /* Add next level of point donations to the label */ 5435f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPartitionLabelAdjacency(dm, ovAdjByRank)); 544be200f8dSMichael Lange } 54526a7d390SMatthew G. Knepley /* We require the closure in the overlap */ 5465f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPartitionLabelClosure(dm, ovAdjByRank)); 5475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-overlap_view", &flg)); 548e540f424SMichael Lange if (flg) { 549825f8a23SLisandro Dalcin PetscViewer viewer; 5505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &viewer)); 5515f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelView(ovAdjByRank, viewer)); 552b0a623aaSMatthew G. Knepley } 553874ddda9SLisandro Dalcin /* Invert sender to receiver label */ 5545f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelCreate(PETSC_COMM_SELF, "Overlap label", ovLabel)); 5555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPartitionLabelInvert(dm, ovAdjByRank, NULL, *ovLabel)); 556a9f1d5b2SMichael Lange /* Add owned points, except for shared local points */ 5575f80ce2aSJacob Faibussowitsch for (p = pStart; p < pEnd; ++p) CHKERRQ(DMLabelSetValue(*ovLabel, p, rank)); 558e540f424SMichael Lange for (l = 0; l < nleaves; ++l) { 5595f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelClearValue(*ovLabel, local[l], rank)); 5605f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetValue(*ovLabel, remote[l].index, remote[l].rank)); 561e540f424SMichael Lange } 562e540f424SMichael Lange /* Clean up */ 5635f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelDestroy(&ovAdjByRank)); 564b0a623aaSMatthew G. Knepley PetscFunctionReturn(0); 565b0a623aaSMatthew G. Knepley } 56670034214SMatthew G. Knepley 56724cc2ca5SMatthew G. Knepley /*@C 56824cc2ca5SMatthew G. Knepley DMPlexCreateOverlapMigrationSF - Create an SF describing the new mesh distribution to make the overlap described by the input SF 56924cc2ca5SMatthew G. Knepley 570d083f849SBarry Smith Collective on dm 57124cc2ca5SMatthew G. Knepley 57224cc2ca5SMatthew G. Knepley Input Parameters: 57324cc2ca5SMatthew G. Knepley + dm - The DM 57424cc2ca5SMatthew G. Knepley - overlapSF - The SF mapping ghost points in overlap to owner points on other processes 57524cc2ca5SMatthew G. Knepley 576064ec1f3Sprj- Output Parameter: 577a2b725a8SWilliam Gropp . migrationSF - An SF that maps original points in old locations to points in new locations 57824cc2ca5SMatthew G. Knepley 57924cc2ca5SMatthew G. Knepley Level: developer 58024cc2ca5SMatthew G. Knepley 581dccdeccaSVaclav Hapla .seealso: DMPlexCreateOverlapLabel(), DMPlexDistributeOverlap(), DMPlexDistribute() 58224cc2ca5SMatthew G. Knepley @*/ 58346f9b1c3SMichael Lange PetscErrorCode DMPlexCreateOverlapMigrationSF(DM dm, PetscSF overlapSF, PetscSF *migrationSF) 58446f9b1c3SMichael Lange { 58546f9b1c3SMichael Lange MPI_Comm comm; 5869852e123SBarry Smith PetscMPIInt rank, size; 58746f9b1c3SMichael Lange PetscInt d, dim, p, pStart, pEnd, nroots, nleaves, newLeaves, point, numSharedPoints; 58846f9b1c3SMichael Lange PetscInt *pointDepths, *remoteDepths, *ilocal; 58946f9b1c3SMichael Lange PetscInt *depthRecv, *depthShift, *depthIdx; 59046f9b1c3SMichael Lange PetscSFNode *iremote; 59146f9b1c3SMichael Lange PetscSF pointSF; 59246f9b1c3SMichael Lange const PetscInt *sharedLocal; 59346f9b1c3SMichael Lange const PetscSFNode *overlapRemote, *sharedRemote; 59446f9b1c3SMichael Lange 59546f9b1c3SMichael Lange PetscFunctionBegin; 59646f9b1c3SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm)); 5985f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 5995f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 6005f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 60146f9b1c3SMichael Lange 60246f9b1c3SMichael Lange /* Before building the migration SF we need to know the new stratum offsets */ 6035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(overlapSF, &nroots, &nleaves, NULL, &overlapRemote)); 6045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths)); 60546f9b1c3SMichael Lange for (d=0; d<dim+1; d++) { 6065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 60746f9b1c3SMichael Lange for (p=pStart; p<pEnd; p++) pointDepths[p] = d; 60846f9b1c3SMichael Lange } 60946f9b1c3SMichael Lange for (p=0; p<nleaves; p++) remoteDepths[p] = -1; 6105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(overlapSF, MPIU_INT, pointDepths, remoteDepths,MPI_REPLACE)); 6115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(overlapSF, MPIU_INT, pointDepths, remoteDepths,MPI_REPLACE)); 61246f9b1c3SMichael Lange 6132d4ee042Sprj- /* Count received points in each stratum and compute the internal strata shift */ 6145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(dim+1, &depthRecv, dim+1, &depthShift, dim+1, &depthIdx)); 61546f9b1c3SMichael Lange for (d=0; d<dim+1; d++) depthRecv[d]=0; 61646f9b1c3SMichael Lange for (p=0; p<nleaves; p++) depthRecv[remoteDepths[p]]++; 61746f9b1c3SMichael Lange depthShift[dim] = 0; 61846f9b1c3SMichael Lange for (d=0; d<dim; d++) depthShift[d] = depthRecv[dim]; 61946f9b1c3SMichael Lange for (d=1; d<dim; d++) depthShift[d] += depthRecv[0]; 62046f9b1c3SMichael Lange for (d=dim-2; d>0; d--) depthShift[d] += depthRecv[d+1]; 62146f9b1c3SMichael Lange for (d=0; d<dim+1; d++) { 6225f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 62346f9b1c3SMichael Lange depthIdx[d] = pStart + depthShift[d]; 62446f9b1c3SMichael Lange } 62546f9b1c3SMichael Lange 62646f9b1c3SMichael Lange /* Form the overlap SF build an SF that describes the full overlap migration SF */ 6275f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 62846f9b1c3SMichael Lange newLeaves = pEnd - pStart + nleaves; 6295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(newLeaves, &ilocal)); 6305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(newLeaves, &iremote)); 63146f9b1c3SMichael Lange /* First map local points to themselves */ 63246f9b1c3SMichael Lange for (d=0; d<dim+1; d++) { 6335f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 63446f9b1c3SMichael Lange for (p=pStart; p<pEnd; p++) { 63546f9b1c3SMichael Lange point = p + depthShift[d]; 63646f9b1c3SMichael Lange ilocal[point] = point; 63746f9b1c3SMichael Lange iremote[point].index = p; 63846f9b1c3SMichael Lange iremote[point].rank = rank; 63946f9b1c3SMichael Lange depthIdx[d]++; 64046f9b1c3SMichael Lange } 64146f9b1c3SMichael Lange } 64246f9b1c3SMichael Lange 64346f9b1c3SMichael Lange /* Add in the remote roots for currently shared points */ 6445f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &pointSF)); 6455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(pointSF, NULL, &numSharedPoints, &sharedLocal, &sharedRemote)); 64646f9b1c3SMichael Lange for (d=0; d<dim+1; d++) { 6475f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 64846f9b1c3SMichael Lange for (p=0; p<numSharedPoints; p++) { 64946f9b1c3SMichael Lange if (pStart <= sharedLocal[p] && sharedLocal[p] < pEnd) { 65046f9b1c3SMichael Lange point = sharedLocal[p] + depthShift[d]; 65146f9b1c3SMichael Lange iremote[point].index = sharedRemote[p].index; 65246f9b1c3SMichael Lange iremote[point].rank = sharedRemote[p].rank; 65346f9b1c3SMichael Lange } 65446f9b1c3SMichael Lange } 65546f9b1c3SMichael Lange } 65646f9b1c3SMichael Lange 65746f9b1c3SMichael Lange /* Now add the incoming overlap points */ 65846f9b1c3SMichael Lange for (p=0; p<nleaves; p++) { 65946f9b1c3SMichael Lange point = depthIdx[remoteDepths[p]]; 66046f9b1c3SMichael Lange ilocal[point] = point; 66146f9b1c3SMichael Lange iremote[point].index = overlapRemote[p].index; 66246f9b1c3SMichael Lange iremote[point].rank = overlapRemote[p].rank; 66346f9b1c3SMichael Lange depthIdx[remoteDepths[p]]++; 66446f9b1c3SMichael Lange } 6655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(pointDepths,remoteDepths)); 66646f9b1c3SMichael Lange 6675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreate(comm, migrationSF)); 6685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) *migrationSF, "Overlap Migration SF")); 6695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetFromOptions(*migrationSF)); 6705f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 6715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraph(*migrationSF, pEnd-pStart, newLeaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 67246f9b1c3SMichael Lange 6735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(depthRecv, depthShift, depthIdx)); 67470034214SMatthew G. Knepley PetscFunctionReturn(0); 67570034214SMatthew G. Knepley } 67670034214SMatthew G. Knepley 677a9f1d5b2SMichael Lange /*@ 678f0e73a3dSToby Isaac DMPlexStratifyMigrationSF - Rearrange the leaves of a migration sf for stratification. 679a9f1d5b2SMichael Lange 680064ec1f3Sprj- Input Parameters: 681a9f1d5b2SMichael Lange + dm - The DM 682a9f1d5b2SMichael Lange - sf - A star forest with non-ordered leaves, usually defining a DM point migration 683a9f1d5b2SMichael Lange 684a9f1d5b2SMichael Lange Output Parameter: 685a9f1d5b2SMichael Lange . migrationSF - A star forest with added leaf indirection that ensures the resulting DM is stratified 686a9f1d5b2SMichael Lange 687412e9a14SMatthew G. Knepley Note: 688412e9a14SMatthew G. Knepley This lexicographically sorts by (depth, cellType) 689412e9a14SMatthew G. Knepley 690a9f1d5b2SMichael Lange Level: developer 691a9f1d5b2SMichael Lange 692a9f1d5b2SMichael Lange .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexDistributeOverlap() 693a9f1d5b2SMichael Lange @*/ 694a9f1d5b2SMichael Lange PetscErrorCode DMPlexStratifyMigrationSF(DM dm, PetscSF sf, PetscSF *migrationSF) 695a9f1d5b2SMichael Lange { 696a9f1d5b2SMichael Lange MPI_Comm comm; 6979852e123SBarry Smith PetscMPIInt rank, size; 698412e9a14SMatthew G. Knepley PetscInt d, ldepth, depth, dim, p, pStart, pEnd, nroots, nleaves; 699412e9a14SMatthew G. Knepley PetscSFNode *pointDepths, *remoteDepths; 700412e9a14SMatthew G. Knepley PetscInt *ilocal; 701a9f1d5b2SMichael Lange PetscInt *depthRecv, *depthShift, *depthIdx; 702412e9a14SMatthew G. Knepley PetscInt *ctRecv, *ctShift, *ctIdx; 703a9f1d5b2SMichael Lange const PetscSFNode *iremote; 704a9f1d5b2SMichael Lange 705a9f1d5b2SMichael Lange PetscFunctionBegin; 706a9f1d5b2SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 7085f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 7095f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 7105f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &ldepth)); 7115f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 7125f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&ldepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 7132c71b3e2SJacob Faibussowitsch PetscCheckFalse((ldepth >= 0) && (depth != ldepth),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %d != %d", ldepth, depth); 7145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_PartStratSF,dm,0,0,0)); 715a9f1d5b2SMichael Lange 716a9f1d5b2SMichael Lange /* Before building the migration SF we need to know the new stratum offsets */ 7175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, &iremote)); 7185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths)); 7197fab53ddSMatthew G. Knepley for (d = 0; d < depth+1; ++d) { 7205f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 721f0e73a3dSToby Isaac for (p = pStart; p < pEnd; ++p) { 722412e9a14SMatthew G. Knepley DMPolytopeType ct; 723f0e73a3dSToby Isaac 7245f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, p, &ct)); 725412e9a14SMatthew G. Knepley pointDepths[p].index = d; 726412e9a14SMatthew G. Knepley pointDepths[p].rank = ct; 727f0e73a3dSToby Isaac } 728412e9a14SMatthew G. Knepley } 729412e9a14SMatthew G. Knepley for (p = 0; p < nleaves; ++p) {remoteDepths[p].index = -1; remoteDepths[p].rank = -1;} 7305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sf, MPIU_2INT, pointDepths, remoteDepths,MPI_REPLACE)); 7315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sf, MPIU_2INT, pointDepths, remoteDepths,MPI_REPLACE)); 732412e9a14SMatthew G. Knepley /* Count received points in each stratum and compute the internal strata shift */ 7335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc6(depth+1, &depthRecv, depth+1, &depthShift, depth+1, &depthIdx, DM_NUM_POLYTOPES, &ctRecv, DM_NUM_POLYTOPES, &ctShift, DM_NUM_POLYTOPES, &ctIdx)); 734412e9a14SMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 735412e9a14SMatthew G. Knepley if (remoteDepths[p].rank < 0) { 736412e9a14SMatthew G. Knepley ++depthRecv[remoteDepths[p].index]; 737412e9a14SMatthew G. Knepley } else { 738412e9a14SMatthew G. Knepley ++ctRecv[remoteDepths[p].rank]; 739412e9a14SMatthew G. Knepley } 740412e9a14SMatthew G. Knepley } 741412e9a14SMatthew G. Knepley { 742412e9a14SMatthew G. Knepley PetscInt depths[4], dims[4], shift = 0, i, c; 743412e9a14SMatthew G. Knepley 7448238f61eSMatthew G. Knepley /* Cells (depth), Vertices (0), Faces (depth-1), Edges (1) 7458238f61eSMatthew G. Knepley Consider DM_POLYTOPE_FV_GHOST and DM_POLYTOPE_INTERIOR_GHOST as cells 7468238f61eSMatthew G. Knepley */ 747412e9a14SMatthew G. Knepley depths[0] = depth; depths[1] = 0; depths[2] = depth-1; depths[3] = 1; 748412e9a14SMatthew G. Knepley dims[0] = dim; dims[1] = 0; dims[2] = dim-1; dims[3] = 1; 749412e9a14SMatthew G. Knepley for (i = 0; i <= depth; ++i) { 750412e9a14SMatthew G. Knepley const PetscInt dep = depths[i]; 751412e9a14SMatthew G. Knepley const PetscInt dim = dims[i]; 752412e9a14SMatthew G. Knepley 753412e9a14SMatthew G. Knepley for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 7548238f61eSMatthew G. Knepley if (DMPolytopeTypeGetDim((DMPolytopeType) c) != dim && !(i == 0 && (c == DM_POLYTOPE_FV_GHOST || c == DM_POLYTOPE_INTERIOR_GHOST))) continue; 755412e9a14SMatthew G. Knepley ctShift[c] = shift; 756412e9a14SMatthew G. Knepley shift += ctRecv[c]; 757412e9a14SMatthew G. Knepley } 758412e9a14SMatthew G. Knepley depthShift[dep] = shift; 759412e9a14SMatthew G. Knepley shift += depthRecv[dep]; 760412e9a14SMatthew G. Knepley } 761412e9a14SMatthew G. Knepley for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 762412e9a14SMatthew G. Knepley const PetscInt ctDim = DMPolytopeTypeGetDim((DMPolytopeType) c); 763412e9a14SMatthew G. Knepley 7648238f61eSMatthew G. Knepley if ((ctDim < 0 || ctDim > dim) && (c != DM_POLYTOPE_FV_GHOST && c != DM_POLYTOPE_INTERIOR_GHOST)) { 765412e9a14SMatthew G. Knepley ctShift[c] = shift; 766412e9a14SMatthew G. Knepley shift += ctRecv[c]; 767412e9a14SMatthew G. Knepley } 768412e9a14SMatthew G. Knepley } 769412e9a14SMatthew G. Knepley } 770a9f1d5b2SMichael Lange /* Derive a new local permutation based on stratified indices */ 7715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nleaves, &ilocal)); 7727fab53ddSMatthew G. Knepley for (p = 0; p < nleaves; ++p) { 773412e9a14SMatthew G. Knepley const PetscInt dep = remoteDepths[p].index; 774412e9a14SMatthew G. Knepley const DMPolytopeType ct = (DMPolytopeType) remoteDepths[p].rank; 7757fab53ddSMatthew G. Knepley 776412e9a14SMatthew G. Knepley if ((PetscInt) ct < 0) { 7777fab53ddSMatthew G. Knepley ilocal[p] = depthShift[dep] + depthIdx[dep]; 778412e9a14SMatthew G. Knepley ++depthIdx[dep]; 779412e9a14SMatthew G. Knepley } else { 780412e9a14SMatthew G. Knepley ilocal[p] = ctShift[ct] + ctIdx[ct]; 781412e9a14SMatthew G. Knepley ++ctIdx[ct]; 782412e9a14SMatthew G. Knepley } 783a9f1d5b2SMichael Lange } 7845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreate(comm, migrationSF)); 7855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) *migrationSF, "Migration SF")); 7865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraph(*migrationSF, nroots, nleaves, ilocal, PETSC_OWN_POINTER, (PetscSFNode*)iremote, PETSC_COPY_VALUES)); 7875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(pointDepths,remoteDepths)); 7885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree6(depthRecv, depthShift, depthIdx, ctRecv, ctShift, ctIdx)); 7895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_PartStratSF,dm,0,0,0)); 790a9f1d5b2SMichael Lange PetscFunctionReturn(0); 791a9f1d5b2SMichael Lange } 792a9f1d5b2SMichael Lange 79370034214SMatthew G. Knepley /*@ 79470034214SMatthew G. Knepley DMPlexDistributeField - Distribute field data to match a given PetscSF, usually the SF from mesh distribution 79570034214SMatthew G. Knepley 796d083f849SBarry Smith Collective on dm 79770034214SMatthew G. Knepley 79870034214SMatthew G. Knepley Input Parameters: 79970034214SMatthew G. Knepley + dm - The DMPlex object 80070034214SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern 80170034214SMatthew G. Knepley . originalSection - The PetscSection for existing data layout 802cb15cd0eSMatthew G. Knepley - originalVec - The existing data in a local vector 80370034214SMatthew G. Knepley 80470034214SMatthew G. Knepley Output Parameters: 80570034214SMatthew G. Knepley + newSection - The PetscSF describing the new data layout 806cb15cd0eSMatthew G. Knepley - newVec - The new data in a local vector 80770034214SMatthew G. Knepley 80870034214SMatthew G. Knepley Level: developer 80970034214SMatthew G. Knepley 81070034214SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeFieldIS(), DMPlexDistributeData() 81170034214SMatthew G. Knepley @*/ 81270034214SMatthew G. Knepley PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 81370034214SMatthew G. Knepley { 81470034214SMatthew G. Knepley PetscSF fieldSF; 81570034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize; 81670034214SMatthew G. Knepley PetscScalar *originalValues, *newValues; 81770034214SMatthew G. Knepley 81870034214SMatthew G. Knepley PetscFunctionBegin; 8195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeField,dm,0,0,0)); 8205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 82170034214SMatthew G. Knepley 8225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(newSection, &fieldSize)); 8235f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(newVec, fieldSize, PETSC_DETERMINE)); 8245f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(newVec,dm->vectype)); 82570034214SMatthew G. Knepley 8265f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(originalVec, &originalValues)); 8275f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(newVec, &newValues)); 8285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 8295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(remoteOffsets)); 8305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues,MPI_REPLACE)); 8315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues,MPI_REPLACE)); 8325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&fieldSF)); 8335f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(newVec, &newValues)); 8345f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(originalVec, &originalValues)); 8355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeField,dm,0,0,0)); 83670034214SMatthew G. Knepley PetscFunctionReturn(0); 83770034214SMatthew G. Knepley } 83870034214SMatthew G. Knepley 83970034214SMatthew G. Knepley /*@ 84070034214SMatthew G. Knepley DMPlexDistributeFieldIS - Distribute field data to match a given PetscSF, usually the SF from mesh distribution 84170034214SMatthew G. Knepley 842d083f849SBarry Smith Collective on dm 84370034214SMatthew G. Knepley 84470034214SMatthew G. Knepley Input Parameters: 84570034214SMatthew G. Knepley + dm - The DMPlex object 84670034214SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern 84770034214SMatthew G. Knepley . originalSection - The PetscSection for existing data layout 84870034214SMatthew G. Knepley - originalIS - The existing data 84970034214SMatthew G. Knepley 85070034214SMatthew G. Knepley Output Parameters: 85170034214SMatthew G. Knepley + newSection - The PetscSF describing the new data layout 85270034214SMatthew G. Knepley - newIS - The new data 85370034214SMatthew G. Knepley 85470034214SMatthew G. Knepley Level: developer 85570034214SMatthew G. Knepley 85670034214SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexDistributeData() 85770034214SMatthew G. Knepley @*/ 85870034214SMatthew G. Knepley PetscErrorCode DMPlexDistributeFieldIS(DM dm, PetscSF pointSF, PetscSection originalSection, IS originalIS, PetscSection newSection, IS *newIS) 85970034214SMatthew G. Knepley { 86070034214SMatthew G. Knepley PetscSF fieldSF; 86170034214SMatthew G. Knepley PetscInt *newValues, *remoteOffsets, fieldSize; 86270034214SMatthew G. Knepley const PetscInt *originalValues; 86370034214SMatthew G. Knepley 86470034214SMatthew G. Knepley PetscFunctionBegin; 8655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeField,dm,0,0,0)); 8665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 86770034214SMatthew G. Knepley 8685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(newSection, &fieldSize)); 8695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(fieldSize, &newValues)); 87070034214SMatthew G. Knepley 8715f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(originalIS, &originalValues)); 8725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 8735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(remoteOffsets)); 8745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(fieldSF, MPIU_INT, (PetscInt *) originalValues, newValues,MPI_REPLACE)); 8755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(fieldSF, MPIU_INT, (PetscInt *) originalValues, newValues,MPI_REPLACE)); 8765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&fieldSF)); 8775f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(originalIS, &originalValues)); 8785f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject) pointSF), fieldSize, newValues, PETSC_OWN_POINTER, newIS)); 8795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeField,dm,0,0,0)); 88070034214SMatthew G. Knepley PetscFunctionReturn(0); 88170034214SMatthew G. Knepley } 88270034214SMatthew G. Knepley 88370034214SMatthew G. Knepley /*@ 88470034214SMatthew G. Knepley DMPlexDistributeData - Distribute field data to match a given PetscSF, usually the SF from mesh distribution 88570034214SMatthew G. Knepley 886d083f849SBarry Smith Collective on dm 88770034214SMatthew G. Knepley 88870034214SMatthew G. Knepley Input Parameters: 88970034214SMatthew G. Knepley + dm - The DMPlex object 89070034214SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern 89170034214SMatthew G. Knepley . originalSection - The PetscSection for existing data layout 89270034214SMatthew G. Knepley . datatype - The type of data 89370034214SMatthew G. Knepley - originalData - The existing data 89470034214SMatthew G. Knepley 89570034214SMatthew G. Knepley Output Parameters: 89670034214SMatthew G. Knepley + newSection - The PetscSection describing the new data layout 89770034214SMatthew G. Knepley - newData - The new data 89870034214SMatthew G. Knepley 89970034214SMatthew G. Knepley Level: developer 90070034214SMatthew G. Knepley 90170034214SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField() 90270034214SMatthew G. Knepley @*/ 90370034214SMatthew G. Knepley PetscErrorCode DMPlexDistributeData(DM dm, PetscSF pointSF, PetscSection originalSection, MPI_Datatype datatype, void *originalData, PetscSection newSection, void **newData) 90470034214SMatthew G. Knepley { 90570034214SMatthew G. Knepley PetscSF fieldSF; 90670034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize; 90770034214SMatthew G. Knepley PetscMPIInt dataSize; 90870034214SMatthew G. Knepley 90970034214SMatthew G. Knepley PetscFunctionBegin; 9105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeData,dm,0,0,0)); 9115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection)); 91270034214SMatthew G. Knepley 9135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(newSection, &fieldSize)); 9145f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_size(datatype, &dataSize)); 9155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc(fieldSize * dataSize, newData)); 91670034214SMatthew G. Knepley 9175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF)); 9185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(remoteOffsets)); 9195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(fieldSF, datatype, originalData, *newData,MPI_REPLACE)); 9205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(fieldSF, datatype, originalData, *newData,MPI_REPLACE)); 9215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&fieldSF)); 9225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeData,dm,0,0,0)); 92370034214SMatthew G. Knepley PetscFunctionReturn(0); 92470034214SMatthew G. Knepley } 92570034214SMatthew G. Knepley 92624cc2ca5SMatthew G. Knepley static PetscErrorCode DMPlexDistributeCones(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel) 927cc71bff1SMichael Lange { 928cc71bff1SMichael Lange DM_Plex *pmesh = (DM_Plex*) (dmParallel)->data; 929cc71bff1SMichael Lange MPI_Comm comm; 930cc71bff1SMichael Lange PetscSF coneSF; 931cc71bff1SMichael Lange PetscSection originalConeSection, newConeSection; 932ac04eaf7SToby Isaac PetscInt *remoteOffsets, *cones, *globCones, *newCones, newConesSize; 933cc71bff1SMichael Lange PetscBool flg; 934cc71bff1SMichael Lange 935cc71bff1SMichael Lange PetscFunctionBegin; 936cc71bff1SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9370c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5); 9385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeCones,dm,0,0,0)); 939cc71bff1SMichael Lange /* Distribute cone section */ 9405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm)); 9415f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSection(dm, &originalConeSection)); 9425f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeSection(dmParallel, &newConeSection)); 9435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDistributeSection(migrationSF, originalConeSection, &remoteOffsets, newConeSection)); 9445f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(dmParallel)); 945cc71bff1SMichael Lange { 946cc71bff1SMichael Lange PetscInt pStart, pEnd, p; 947cc71bff1SMichael Lange 9485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(newConeSection, &pStart, &pEnd)); 949cc71bff1SMichael Lange for (p = pStart; p < pEnd; ++p) { 950cc71bff1SMichael Lange PetscInt coneSize; 9515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(newConeSection, p, &coneSize)); 952cc71bff1SMichael Lange pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 953cc71bff1SMichael Lange } 954cc71bff1SMichael Lange } 955cc71bff1SMichael Lange /* Communicate and renumber cones */ 9565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateSectionSF(migrationSF, originalConeSection, remoteOffsets, newConeSection, &coneSF)); 9575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(remoteOffsets)); 9585f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCones(dm, &cones)); 959ac04eaf7SToby Isaac if (original) { 960ac04eaf7SToby Isaac PetscInt numCones; 961ac04eaf7SToby Isaac 9625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(originalConeSection,&numCones)); 9635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numCones,&globCones)); 9645f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApplyBlock(original, numCones, cones, globCones)); 965367003a6SStefano Zampini } else { 966ac04eaf7SToby Isaac globCones = cones; 967ac04eaf7SToby Isaac } 9685f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCones(dmParallel, &newCones)); 9695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(coneSF, MPIU_INT, globCones, newCones,MPI_REPLACE)); 9705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(coneSF, MPIU_INT, globCones, newCones,MPI_REPLACE)); 971ac04eaf7SToby Isaac if (original) { 9725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(globCones)); 973ac04eaf7SToby Isaac } 9745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(newConeSection, &newConesSize)); 9755f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones)); 97676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 9773533c52bSMatthew G. Knepley PetscInt p; 9783533c52bSMatthew G. Knepley PetscBool valid = PETSC_TRUE; 9793533c52bSMatthew G. Knepley for (p = 0; p < newConesSize; ++p) { 9805f80ce2aSJacob Faibussowitsch if (newCones[p] < 0) {valid = PETSC_FALSE; CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "[%d] Point %D not in overlap SF\n", PetscGlobalRank,p));} 9813533c52bSMatthew G. Knepley } 982*28b400f6SJacob Faibussowitsch PetscCheck(valid,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map"); 9833533c52bSMatthew G. Knepley } 9845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-cones_view", &flg)); 985cc71bff1SMichael Lange if (flg) { 9865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(comm, "Serial Cone Section:\n")); 9875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_(comm))); 9885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(comm, "Parallel Cone Section:\n")); 9895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_(comm))); 9905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFView(coneSF, NULL)); 991cc71bff1SMichael Lange } 9925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientations(dm, &cones)); 9935f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetConeOrientations(dmParallel, &newCones)); 9945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones,MPI_REPLACE)); 9955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones,MPI_REPLACE)); 9965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&coneSF)); 9975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeCones,dm,0,0,0)); 998eaf898f9SPatrick Sanan /* Create supports and stratify DMPlex */ 999cc71bff1SMichael Lange { 1000cc71bff1SMichael Lange PetscInt pStart, pEnd; 1001cc71bff1SMichael Lange 10025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd)); 10035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(pmesh->supportSection, pStart, pEnd)); 1004cc71bff1SMichael Lange } 10055f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSymmetrize(dmParallel)); 10065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratify(dmParallel)); 10071cf84007SMatthew G. Knepley { 10081cf84007SMatthew G. Knepley PetscBool useCone, useClosure, useAnchors; 10091cf84007SMatthew G. Knepley 10105f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 10115f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetBasicAdjacency(dmParallel, useCone, useClosure)); 10125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors)); 10135f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetAdjacencyUseAnchors(dmParallel, useAnchors)); 10141cf84007SMatthew G. Knepley } 1015cc71bff1SMichael Lange PetscFunctionReturn(0); 1016cc71bff1SMichael Lange } 1017cc71bff1SMichael Lange 101824cc2ca5SMatthew G. Knepley static PetscErrorCode DMPlexDistributeCoordinates(DM dm, PetscSF migrationSF, DM dmParallel) 10190df0e737SMichael Lange { 10200df0e737SMichael Lange MPI_Comm comm; 10219318fe57SMatthew G. Knepley DM cdm, cdmParallel; 10220df0e737SMichael Lange PetscSection originalCoordSection, newCoordSection; 10230df0e737SMichael Lange Vec originalCoordinates, newCoordinates; 10240df0e737SMichael Lange PetscInt bs; 102590b157c4SStefano Zampini PetscBool isper; 10260df0e737SMichael Lange const char *name; 10270df0e737SMichael Lange const PetscReal *maxCell, *L; 10285dc8c3f7SMatthew G. Knepley const DMBoundaryType *bd; 10290df0e737SMichael Lange 10300df0e737SMichael Lange PetscFunctionBegin; 10310df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10320c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3); 10330df0e737SMichael Lange 10345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm)); 10355f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dm, &originalCoordSection)); 10365f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateSection(dmParallel, &newCoordSection)); 10375f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &originalCoordinates)); 10380df0e737SMichael Lange if (originalCoordinates) { 10395f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &newCoordinates)); 10405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) originalCoordinates, &name)); 10415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) newCoordinates, name)); 10420df0e737SMichael Lange 10435f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates)); 10445f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinatesLocal(dmParallel, newCoordinates)); 10455f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetBlockSize(originalCoordinates, &bs)); 10465f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(newCoordinates, bs)); 10475f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&newCoordinates)); 10480df0e737SMichael Lange } 10495f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd)); 10505f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPeriodicity(dmParallel, isper, maxCell, L, bd)); 10515f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &cdm)); 10525f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dmParallel, &cdmParallel)); 10535f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyDisc(cdm, cdmParallel)); 10540df0e737SMichael Lange PetscFunctionReturn(0); 10550df0e737SMichael Lange } 10560df0e737SMichael Lange 105724cc2ca5SMatthew G. Knepley static PetscErrorCode DMPlexDistributeLabels(DM dm, PetscSF migrationSF, DM dmParallel) 10580df0e737SMichael Lange { 1059df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 10600df0e737SMichael Lange MPI_Comm comm; 10617980c9d4SMatthew G. Knepley DMLabel depthLabel; 10620df0e737SMichael Lange PetscMPIInt rank; 10637980c9d4SMatthew G. Knepley PetscInt depth, d, numLabels, numLocalLabels, l; 1064df0420ecSMatthew G. Knepley PetscBool hasLabels = PETSC_FALSE, lsendDepth, sendDepth; 1065df0420ecSMatthew G. Knepley PetscObjectState depthState = -1; 10660df0e737SMichael Lange 10670df0e737SMichael Lange PetscFunctionBegin; 10680df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10690c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3); 10700c86c063SLisandro Dalcin 10715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeLabels,dm,0,0,0)); 10725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm)); 10735f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 10740df0e737SMichael Lange 1075df0420ecSMatthew G. Knepley /* If the user has changed the depth label, communicate it instead */ 10765f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(dm, &depth)); 10775f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthLabel(dm, &depthLabel)); 10785f80ce2aSJacob Faibussowitsch if (depthLabel) CHKERRQ(PetscObjectStateGet((PetscObject) depthLabel, &depthState)); 1079df0420ecSMatthew G. Knepley lsendDepth = mesh->depthState != depthState ? PETSC_TRUE : PETSC_FALSE; 10805f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&lsendDepth, &sendDepth, 1, MPIU_BOOL, MPI_LOR, comm)); 1081df0420ecSMatthew G. Knepley if (sendDepth) { 10825f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepthLabel(dmParallel, &dmParallel->depthLabel)); 10835f80ce2aSJacob Faibussowitsch CHKERRQ(DMRemoveLabelBySelf(dmParallel, &dmParallel->depthLabel, PETSC_FALSE)); 1084df0420ecSMatthew G. Knepley } 1085d995df53SMatthew G. Knepley /* Everyone must have either the same number of labels, or none */ 10865f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumLabels(dm, &numLocalLabels)); 1087d995df53SMatthew G. Knepley numLabels = numLocalLabels; 10885f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm)); 1089627847f0SMatthew G. Knepley if (numLabels == numLocalLabels) hasLabels = PETSC_TRUE; 10905d80c0bfSVaclav Hapla for (l = 0; l < numLabels; ++l) { 1091bdd2d751SMichael Lange DMLabel label = NULL, labelNew = NULL; 109283e10cb3SLisandro Dalcin PetscBool isDepth, lisOutput = PETSC_TRUE, isOutput; 1093d67d17b1SMatthew G. Knepley const char *name = NULL; 10940df0e737SMichael Lange 1095d67d17b1SMatthew G. Knepley if (hasLabels) { 10965f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabelByNum(dm, l, &label)); 10970df0e737SMichael Lange /* Skip "depth" because it is recreated */ 10985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) label, &name)); 10995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(name, "depth", &isDepth)); 1100d67d17b1SMatthew G. Knepley } 11015f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Bcast(&isDepth, 1, MPIU_BOOL, 0, comm)); 110283e10cb3SLisandro Dalcin if (isDepth && !sendDepth) continue; 11035f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelDistribute(label, migrationSF, &labelNew)); 110483e10cb3SLisandro Dalcin if (isDepth) { 11057980c9d4SMatthew G. Knepley /* Put in any missing strata which can occur if users are managing the depth label themselves */ 11067980c9d4SMatthew G. Knepley PetscInt gdepth; 11077980c9d4SMatthew G. Knepley 11085f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&depth, &gdepth, 1, MPIU_INT, MPI_MAX, comm)); 11092c71b3e2SJacob Faibussowitsch PetscCheckFalse((depth >= 0) && (gdepth != depth),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %d != %d", depth, gdepth); 11107980c9d4SMatthew G. Knepley for (d = 0; d <= gdepth; ++d) { 11117980c9d4SMatthew G. Knepley PetscBool has; 11127980c9d4SMatthew G. Knepley 11135f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelHasStratum(labelNew, d, &has)); 11145f80ce2aSJacob Faibussowitsch if (!has) CHKERRQ(DMLabelAddStratum(labelNew, d)); 11157980c9d4SMatthew G. Knepley } 11167980c9d4SMatthew G. Knepley } 11175f80ce2aSJacob Faibussowitsch CHKERRQ(DMAddLabel(dmParallel, labelNew)); 111883e10cb3SLisandro Dalcin /* Put the output flag in the new label */ 11195f80ce2aSJacob Faibussowitsch if (hasLabels) CHKERRQ(DMGetLabelOutput(dm, name, &lisOutput)); 11205f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&lisOutput, &isOutput, 1, MPIU_BOOL, MPI_LAND, comm)); 11215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetName((PetscObject) labelNew, &name)); 11225f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetLabelOutput(dmParallel, name, isOutput)); 11235f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelDestroy(&labelNew)); 11240df0e737SMichael Lange } 11255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeLabels,dm,0,0,0)); 11260df0e737SMichael Lange PetscFunctionReturn(0); 11270df0e737SMichael Lange } 11280df0e737SMichael Lange 112924cc2ca5SMatthew G. Knepley static PetscErrorCode DMPlexDistributeSetupTree(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel) 1130a6f36705SMichael Lange { 113115078cd4SMichael Lange DM_Plex *mesh = (DM_Plex*) dm->data; 113215078cd4SMichael Lange DM_Plex *pmesh = (DM_Plex*) (dmParallel)->data; 1133a6f36705SMichael Lange MPI_Comm comm; 1134a6f36705SMichael Lange DM refTree; 1135a6f36705SMichael Lange PetscSection origParentSection, newParentSection; 1136a6f36705SMichael Lange PetscInt *origParents, *origChildIDs; 1137a6f36705SMichael Lange PetscBool flg; 1138a6f36705SMichael Lange 1139a6f36705SMichael Lange PetscFunctionBegin; 1140a6f36705SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 11410c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 5); 11425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm)); 1143a6f36705SMichael Lange 1144a6f36705SMichael Lange /* Set up tree */ 11455f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetReferenceTree(dm,&refTree)); 11465f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetReferenceTree(dmParallel,refTree)); 11475f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetTree(dm,&origParentSection,&origParents,&origChildIDs,NULL,NULL)); 1148a6f36705SMichael Lange if (origParentSection) { 1149a6f36705SMichael Lange PetscInt pStart, pEnd; 115008633170SToby Isaac PetscInt *newParents, *newChildIDs, *globParents; 1151a6f36705SMichael Lange PetscInt *remoteOffsetsParents, newParentSize; 1152a6f36705SMichael Lange PetscSF parentSF; 1153a6f36705SMichael Lange 11545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dmParallel, &pStart, &pEnd)); 11555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)dmParallel),&newParentSection)); 11565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionSetChart(newParentSection,pStart,pEnd)); 11575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDistributeSection(migrationSF, origParentSection, &remoteOffsetsParents, newParentSection)); 11585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreateSectionSF(migrationSF, origParentSection, remoteOffsetsParents, newParentSection, &parentSF)); 11595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(remoteOffsetsParents)); 11605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(newParentSection,&newParentSize)); 11615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(newParentSize,&newParents,newParentSize,&newChildIDs)); 116208633170SToby Isaac if (original) { 116308633170SToby Isaac PetscInt numParents; 116408633170SToby Isaac 11655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetStorageSize(origParentSection,&numParents)); 11665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numParents,&globParents)); 11675f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApplyBlock(original, numParents, origParents, globParents)); 116808633170SToby Isaac } 116908633170SToby Isaac else { 117008633170SToby Isaac globParents = origParents; 117108633170SToby Isaac } 11725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(parentSF, MPIU_INT, globParents, newParents,MPI_REPLACE)); 11735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(parentSF, MPIU_INT, globParents, newParents,MPI_REPLACE)); 117408633170SToby Isaac if (original) { 11755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(globParents)); 117608633170SToby Isaac } 11775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(parentSF, MPIU_INT, origChildIDs, newChildIDs,MPI_REPLACE)); 11785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(parentSF, MPIU_INT, origChildIDs, newChildIDs,MPI_REPLACE)); 11795f80ce2aSJacob Faibussowitsch CHKERRQ(ISGlobalToLocalMappingApplyBlock(renumbering,IS_GTOLM_MASK, newParentSize, newParents, NULL, newParents)); 118076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 11814a54e071SToby Isaac PetscInt p; 11824a54e071SToby Isaac PetscBool valid = PETSC_TRUE; 11834a54e071SToby Isaac for (p = 0; p < newParentSize; ++p) { 11845f80ce2aSJacob Faibussowitsch if (newParents[p] < 0) {valid = PETSC_FALSE; CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "Point %d not in overlap SF\n", p));} 11854a54e071SToby Isaac } 1186*28b400f6SJacob Faibussowitsch PetscCheck(valid,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map"); 11874a54e071SToby Isaac } 11885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-parents_view", &flg)); 1189a6f36705SMichael Lange if (flg) { 11905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(comm, "Serial Parent Section: \n")); 11915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionView(origParentSection, PETSC_VIEWER_STDOUT_(comm))); 11925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(comm, "Parallel Parent Section: \n")); 11935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionView(newParentSection, PETSC_VIEWER_STDOUT_(comm))); 11945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFView(parentSF, NULL)); 1195a6f36705SMichael Lange } 11965f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetTree(dmParallel,newParentSection,newParents,newChildIDs)); 11975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&newParentSection)); 11985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(newParents,newChildIDs)); 11995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&parentSF)); 1200a6f36705SMichael Lange } 120115078cd4SMichael Lange pmesh->useAnchors = mesh->useAnchors; 1202a6f36705SMichael Lange PetscFunctionReturn(0); 1203a6f36705SMichael Lange } 12040df0e737SMichael Lange 120524cc2ca5SMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexDistributeSF(DM dm, PetscSF migrationSF, DM dmParallel) 12064eca1733SMichael Lange { 12079852e123SBarry Smith PetscMPIInt rank, size; 12084eca1733SMichael Lange MPI_Comm comm; 12094eca1733SMichael Lange 12104eca1733SMichael Lange PetscFunctionBegin; 12114eca1733SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 12120c86c063SLisandro Dalcin PetscValidHeaderSpecific(dmParallel, DM_CLASSID, 3); 12134eca1733SMichael Lange 12144eca1733SMichael Lange /* Create point SF for parallel mesh */ 12155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeSF,dm,0,0,0)); 12165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm)); 12175f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 12185f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 12194eca1733SMichael Lange { 12204eca1733SMichael Lange const PetscInt *leaves; 12214eca1733SMichael Lange PetscSFNode *remotePoints, *rowners, *lowners; 12224eca1733SMichael Lange PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 12234eca1733SMichael Lange PetscInt pStart, pEnd; 12244eca1733SMichael Lange 12255f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dmParallel, &pStart, &pEnd)); 12265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(migrationSF, &numRoots, &numLeaves, &leaves, NULL)); 12275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(numRoots,&rowners,numLeaves,&lowners)); 12284eca1733SMichael Lange for (p=0; p<numRoots; p++) { 12294eca1733SMichael Lange rowners[p].rank = -1; 12304eca1733SMichael Lange rowners[p].index = -1; 12314eca1733SMichael Lange } 12325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(migrationSF, MPIU_2INT, rowners, lowners,MPI_REPLACE)); 12335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(migrationSF, MPIU_2INT, rowners, lowners,MPI_REPLACE)); 12344eca1733SMichael Lange for (p = 0; p < numLeaves; ++p) { 12354eca1733SMichael Lange if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 12364eca1733SMichael Lange lowners[p].rank = rank; 12374eca1733SMichael Lange lowners[p].index = leaves ? leaves[p] : p; 12384eca1733SMichael Lange } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 12394eca1733SMichael Lange lowners[p].rank = -2; 12404eca1733SMichael Lange lowners[p].index = -2; 12414eca1733SMichael Lange } 12424eca1733SMichael Lange } 12434eca1733SMichael Lange for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 12444eca1733SMichael Lange rowners[p].rank = -3; 12454eca1733SMichael Lange rowners[p].index = -3; 12464eca1733SMichael Lange } 12475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceBegin(migrationSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC)); 12485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceEnd(migrationSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC)); 12495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(migrationSF, MPIU_2INT, rowners, lowners,MPI_REPLACE)); 12505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(migrationSF, MPIU_2INT, rowners, lowners,MPI_REPLACE)); 12514eca1733SMichael Lange for (p = 0; p < numLeaves; ++p) { 12522c71b3e2SJacob Faibussowitsch PetscCheckFalse(lowners[p].rank < 0 || lowners[p].index < 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 12534eca1733SMichael Lange if (lowners[p].rank != rank) ++numGhostPoints; 12544eca1733SMichael Lange } 12555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numGhostPoints, &ghostPoints)); 12565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numGhostPoints, &remotePoints)); 12574eca1733SMichael Lange for (p = 0, gp = 0; p < numLeaves; ++p) { 12584eca1733SMichael Lange if (lowners[p].rank != rank) { 12594eca1733SMichael Lange ghostPoints[gp] = leaves ? leaves[p] : p; 12604eca1733SMichael Lange remotePoints[gp].rank = lowners[p].rank; 12614eca1733SMichael Lange remotePoints[gp].index = lowners[p].index; 12624eca1733SMichael Lange ++gp; 12634eca1733SMichael Lange } 12644eca1733SMichael Lange } 12655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(rowners,lowners)); 12665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraph((dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER)); 12675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetFromOptions((dmParallel)->sf)); 12684eca1733SMichael Lange } 12691cf84007SMatthew G. Knepley { 12701cf84007SMatthew G. Knepley PetscBool useCone, useClosure, useAnchors; 12711cf84007SMatthew G. Knepley 12725f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 12735f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetBasicAdjacency(dmParallel, useCone, useClosure)); 12745f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAdjacencyUseAnchors(dm, &useAnchors)); 12755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetAdjacencyUseAnchors(dmParallel, useAnchors)); 12761cf84007SMatthew G. Knepley } 12775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeSF,dm,0,0,0)); 12784eca1733SMichael Lange PetscFunctionReturn(0); 12794eca1733SMichael Lange } 12804eca1733SMichael Lange 128198ba2d7fSLawrence Mitchell /*@ 128298ba2d7fSLawrence Mitchell DMPlexSetPartitionBalance - Should distribution of the DM attempt to balance the shared point partition? 128398ba2d7fSLawrence Mitchell 128498ba2d7fSLawrence Mitchell Input Parameters: 128598ba2d7fSLawrence Mitchell + dm - The DMPlex object 128698ba2d7fSLawrence Mitchell - flg - Balance the partition? 128798ba2d7fSLawrence Mitchell 128898ba2d7fSLawrence Mitchell Level: intermediate 128998ba2d7fSLawrence Mitchell 129098ba2d7fSLawrence Mitchell .seealso: DMPlexDistribute(), DMPlexGetPartitionBalance() 129198ba2d7fSLawrence Mitchell @*/ 129298ba2d7fSLawrence Mitchell PetscErrorCode DMPlexSetPartitionBalance(DM dm, PetscBool flg) 129398ba2d7fSLawrence Mitchell { 129498ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 129598ba2d7fSLawrence Mitchell 129698ba2d7fSLawrence Mitchell PetscFunctionBegin; 129798ba2d7fSLawrence Mitchell mesh->partitionBalance = flg; 129898ba2d7fSLawrence Mitchell PetscFunctionReturn(0); 129998ba2d7fSLawrence Mitchell } 130098ba2d7fSLawrence Mitchell 130198ba2d7fSLawrence Mitchell /*@ 130298ba2d7fSLawrence Mitchell DMPlexGetPartitionBalance - Does distribution of the DM attempt to balance the shared point partition? 130398ba2d7fSLawrence Mitchell 130498ba2d7fSLawrence Mitchell Input Parameter: 1305a2b725a8SWilliam Gropp . dm - The DMPlex object 130698ba2d7fSLawrence Mitchell 130798ba2d7fSLawrence Mitchell Output Parameter: 1308a2b725a8SWilliam Gropp . flg - Balance the partition? 130998ba2d7fSLawrence Mitchell 131098ba2d7fSLawrence Mitchell Level: intermediate 131198ba2d7fSLawrence Mitchell 131298ba2d7fSLawrence Mitchell .seealso: DMPlexDistribute(), DMPlexSetPartitionBalance() 131398ba2d7fSLawrence Mitchell @*/ 131498ba2d7fSLawrence Mitchell PetscErrorCode DMPlexGetPartitionBalance(DM dm, PetscBool *flg) 131598ba2d7fSLawrence Mitchell { 131698ba2d7fSLawrence Mitchell DM_Plex *mesh = (DM_Plex *)dm->data; 131798ba2d7fSLawrence Mitchell 131898ba2d7fSLawrence Mitchell PetscFunctionBegin; 131998ba2d7fSLawrence Mitchell PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1320534a8f05SLisandro Dalcin PetscValidBoolPointer(flg, 2); 132198ba2d7fSLawrence Mitchell *flg = mesh->partitionBalance; 132298ba2d7fSLawrence Mitchell PetscFunctionReturn(0); 132398ba2d7fSLawrence Mitchell } 132498ba2d7fSLawrence Mitchell 1325fc02256fSLawrence Mitchell typedef struct { 1326fc02256fSLawrence Mitchell PetscInt vote, rank, index; 1327fc02256fSLawrence Mitchell } Petsc3Int; 1328fc02256fSLawrence Mitchell 1329fc02256fSLawrence Mitchell /* MaxLoc, but carry a third piece of information around */ 13302eb0eadbSSatish Balay static void MPIAPI MaxLocCarry(void *in_, void *inout_, PetscMPIInt *len_, MPI_Datatype *dtype) 1331fc02256fSLawrence Mitchell { 1332fc02256fSLawrence Mitchell Petsc3Int *a = (Petsc3Int *)inout_; 1333fc02256fSLawrence Mitchell Petsc3Int *b = (Petsc3Int *)in_; 1334fc02256fSLawrence Mitchell PetscInt i, len = *len_; 1335fc02256fSLawrence Mitchell for (i = 0; i < len; i++) { 1336fc02256fSLawrence Mitchell if (a[i].vote < b[i].vote) { 1337fc02256fSLawrence Mitchell a[i].vote = b[i].vote; 1338fc02256fSLawrence Mitchell a[i].rank = b[i].rank; 1339fc02256fSLawrence Mitchell a[i].index = b[i].index; 1340fc02256fSLawrence Mitchell } else if (a[i].vote <= b[i].vote) { 1341fc02256fSLawrence Mitchell if (a[i].rank >= b[i].rank) { 1342fc02256fSLawrence Mitchell a[i].rank = b[i].rank; 1343fc02256fSLawrence Mitchell a[i].index = b[i].index; 1344fc02256fSLawrence Mitchell } 1345fc02256fSLawrence Mitchell } 1346fc02256fSLawrence Mitchell } 1347fc02256fSLawrence Mitchell } 1348fc02256fSLawrence Mitchell 1349f5bf2dbfSMichael Lange /*@C 1350a8c5bd36SStefano Zampini DMPlexCreatePointSF - Build a point SF from an SF describing a point migration 1351f5bf2dbfSMichael Lange 1352064ec1f3Sprj- Input Parameters: 1353f5bf2dbfSMichael Lange + dm - The source DMPlex object 1354f5bf2dbfSMichael Lange . migrationSF - The star forest that describes the parallel point remapping 1355d8d19677SJose E. Roman - ownership - Flag causing a vote to determine point ownership 1356f5bf2dbfSMichael Lange 1357f5bf2dbfSMichael Lange Output Parameter: 1358d8d19677SJose E. Roman . pointSF - The star forest describing the point overlap in the remapped DM 1359f5bf2dbfSMichael Lange 13603618482eSVaclav Hapla Notes: 13613618482eSVaclav Hapla Output pointSF is guaranteed to have the array of local indices (leaves) sorted. 13623618482eSVaclav Hapla 1363f5bf2dbfSMichael Lange Level: developer 1364f5bf2dbfSMichael Lange 1365f5bf2dbfSMichael Lange .seealso: DMPlexDistribute(), DMPlexDistributeOverlap() 1366f5bf2dbfSMichael Lange @*/ 1367f5bf2dbfSMichael Lange PetscErrorCode DMPlexCreatePointSF(DM dm, PetscSF migrationSF, PetscBool ownership, PetscSF *pointSF) 1368f5bf2dbfSMichael Lange { 136923193802SMatthew G. Knepley PetscMPIInt rank, size; 13701627f6ccSMichael Lange PetscInt p, nroots, nleaves, idx, npointLeaves; 1371f5bf2dbfSMichael Lange PetscInt *pointLocal; 1372f5bf2dbfSMichael Lange const PetscInt *leaves; 1373f5bf2dbfSMichael Lange const PetscSFNode *roots; 1374f5bf2dbfSMichael Lange PetscSFNode *rootNodes, *leafNodes, *pointRemote; 137523193802SMatthew G. Knepley Vec shifts; 1376cae3e4f3SLawrence Mitchell const PetscInt numShifts = 13759; 137723193802SMatthew G. Knepley const PetscScalar *shift = NULL; 137823193802SMatthew G. Knepley const PetscBool shiftDebug = PETSC_FALSE; 137998ba2d7fSLawrence Mitchell PetscBool balance; 1380f5bf2dbfSMichael Lange 1381f5bf2dbfSMichael Lange PetscFunctionBegin; 1382f5bf2dbfSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13835f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 13845f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size)); 13855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_CreatePointSF,dm,0,0,0)); 1386f5bf2dbfSMichael Lange 13875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetPartitionBalance(dm, &balance)); 13885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(migrationSF, &nroots, &nleaves, &leaves, &roots)); 13895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(nroots, &rootNodes, nleaves, &leafNodes)); 1390f5bf2dbfSMichael Lange if (ownership) { 1391fc02256fSLawrence Mitchell MPI_Op op; 1392fc02256fSLawrence Mitchell MPI_Datatype datatype; 1393fc02256fSLawrence Mitchell Petsc3Int *rootVote = NULL, *leafVote = NULL; 139423193802SMatthew 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. */ 139598ba2d7fSLawrence Mitchell if (balance) { 139623193802SMatthew G. Knepley PetscRandom r; 139723193802SMatthew G. Knepley 13985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomCreate(PETSC_COMM_SELF, &r)); 13995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomSetInterval(r, 0, 2467*size)); 14005f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &shifts)); 14015f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(shifts, numShifts, numShifts)); 14025f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(shifts, VECSTANDARD)); 14035f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetRandom(shifts, r)); 14045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomDestroy(&r)); 14055f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(shifts, &shift)); 140623193802SMatthew G. Knepley } 140723193802SMatthew G. Knepley 14085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nroots, &rootVote)); 14095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nleaves, &leafVote)); 141023193802SMatthew G. Knepley /* Point ownership vote: Process with highest rank owns shared points */ 1411f5bf2dbfSMichael Lange for (p = 0; p < nleaves; ++p) { 141223193802SMatthew G. Knepley if (shiftDebug) { 14135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSynchronizedPrintf(PetscObjectComm((PetscObject) dm), "[%d] Point %D RemotePoint %D Shift %D MyRank %D\n", rank, leaves ? leaves[p] : p, roots[p].index, (PetscInt) PetscRealPart(shift[roots[p].index%numShifts]), (rank + (shift ? (PetscInt) PetscRealPart(shift[roots[p].index%numShifts]) : 0))%size)); 141423193802SMatthew G. Knepley } 1415f5bf2dbfSMichael Lange /* Either put in a bid or we know we own it */ 1416fc02256fSLawrence Mitchell leafVote[p].vote = (rank + (shift ? (PetscInt) PetscRealPart(shift[roots[p].index%numShifts]) : 0))%size; 1417fc02256fSLawrence Mitchell leafVote[p].rank = rank; 1418fc02256fSLawrence Mitchell leafVote[p].index = p; 1419f5bf2dbfSMichael Lange } 1420f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) { 14211627f6ccSMichael Lange /* Root must not participate in the reduction, flag so that MAXLOC does not use */ 1422fc02256fSLawrence Mitchell rootVote[p].vote = -3; 1423fc02256fSLawrence Mitchell rootVote[p].rank = -3; 1424fc02256fSLawrence Mitchell rootVote[p].index = -3; 1425f5bf2dbfSMichael Lange } 14265f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_contiguous(3, MPIU_INT, &datatype)); 14275f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_commit(&datatype)); 14285f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Op_create(&MaxLocCarry, 1, &op)); 14295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceBegin(migrationSF, datatype, leafVote, rootVote, op)); 14305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFReduceEnd(migrationSF, datatype, leafVote, rootVote, op)); 14315f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Op_free(&op)); 14325f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Type_free(&datatype)); 1433c091126eSLawrence Mitchell for (p = 0; p < nroots; p++) { 1434fc02256fSLawrence Mitchell rootNodes[p].rank = rootVote[p].rank; 1435fc02256fSLawrence Mitchell rootNodes[p].index = rootVote[p].index; 1436c091126eSLawrence Mitchell } 14375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(leafVote)); 14385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(rootVote)); 1439f5bf2dbfSMichael Lange } else { 1440f5bf2dbfSMichael Lange for (p = 0; p < nroots; p++) { 1441f5bf2dbfSMichael Lange rootNodes[p].index = -1; 1442f5bf2dbfSMichael Lange rootNodes[p].rank = rank; 1443fc02256fSLawrence Mitchell } 1444f5bf2dbfSMichael Lange for (p = 0; p < nleaves; p++) { 1445f5bf2dbfSMichael Lange /* Write new local id into old location */ 1446f5bf2dbfSMichael Lange if (roots[p].rank == rank) { 14476462276dSToby Isaac rootNodes[roots[p].index].index = leaves ? leaves[p] : p; 1448f5bf2dbfSMichael Lange } 1449f5bf2dbfSMichael Lange } 1450f5bf2dbfSMichael Lange } 14515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(migrationSF, MPIU_2INT, rootNodes, leafNodes,MPI_REPLACE)); 14525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(migrationSF, MPIU_2INT, rootNodes, leafNodes,MPI_REPLACE)); 1453f5bf2dbfSMichael Lange 145423193802SMatthew G. Knepley for (npointLeaves = 0, p = 0; p < nleaves; p++) { 1455b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) npointLeaves++; 145623193802SMatthew G. Knepley } 14575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(npointLeaves, &pointLocal)); 14585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(npointLeaves, &pointRemote)); 1459f5bf2dbfSMichael Lange for (idx = 0, p = 0; p < nleaves; p++) { 1460b0e1264bSMatthew G. Knepley if (leafNodes[p].rank != rank) { 14613618482eSVaclav Hapla /* Note that pointLocal is automatically sorted as it is sublist of 0, ..., nleaves-1 */ 1462f5bf2dbfSMichael Lange pointLocal[idx] = p; 1463f5bf2dbfSMichael Lange pointRemote[idx] = leafNodes[p]; 1464f5bf2dbfSMichael Lange idx++; 1465f5bf2dbfSMichael Lange } 1466f5bf2dbfSMichael Lange } 146723193802SMatthew G. Knepley if (shift) { 14685f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(shifts, &shift)); 14695f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&shifts)); 147023193802SMatthew G. Knepley } 14715f80ce2aSJacob Faibussowitsch if (shiftDebug) CHKERRQ(PetscSynchronizedFlush(PetscObjectComm((PetscObject) dm), PETSC_STDOUT)); 14725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreate(PetscObjectComm((PetscObject) dm), pointSF)); 14735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetFromOptions(*pointSF)); 14745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraph(*pointSF, nleaves, npointLeaves, pointLocal, PETSC_OWN_POINTER, pointRemote, PETSC_OWN_POINTER)); 14755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(rootNodes, leafNodes)); 14765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_CreatePointSF,dm,0,0,0)); 1477f5bf2dbfSMichael Lange PetscFunctionReturn(0); 1478f5bf2dbfSMichael Lange } 1479f5bf2dbfSMichael Lange 148015078cd4SMichael Lange /*@C 148115078cd4SMichael Lange DMPlexMigrate - Migrates internal DM data over the supplied star forest 148215078cd4SMichael Lange 1483d083f849SBarry Smith Collective on dm 148483655b49SVáclav Hapla 1485064ec1f3Sprj- Input Parameters: 148615078cd4SMichael Lange + dm - The source DMPlex object 1487d8d19677SJose E. Roman - sf - The star forest communication context describing the migration pattern 148815078cd4SMichael Lange 148915078cd4SMichael Lange Output Parameter: 1490d8d19677SJose E. Roman . targetDM - The target DMPlex object 149115078cd4SMichael Lange 1492b9f40539SMichael Lange Level: intermediate 149315078cd4SMichael Lange 149415078cd4SMichael Lange .seealso: DMPlexDistribute(), DMPlexDistributeOverlap() 149515078cd4SMichael Lange @*/ 1496b9f40539SMichael Lange PetscErrorCode DMPlexMigrate(DM dm, PetscSF sf, DM targetDM) 149715078cd4SMichael Lange { 1498b9f40539SMichael Lange MPI_Comm comm; 1499cc1750acSStefano Zampini PetscInt dim, cdim, nroots; 1500b9f40539SMichael Lange PetscSF sfPoint; 150115078cd4SMichael Lange ISLocalToGlobalMapping ltogMigration; 1502ac04eaf7SToby Isaac ISLocalToGlobalMapping ltogOriginal = NULL; 1503b9f40539SMichael Lange PetscBool flg; 150415078cd4SMichael Lange 150515078cd4SMichael Lange PetscFunctionBegin; 150615078cd4SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 15075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_Migrate, dm, 0, 0, 0)); 15085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm)); 15095f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 15105f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(targetDM, dim)); 15115f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm, &cdim)); 15125f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetCoordinateDim(targetDM, cdim)); 151315078cd4SMichael Lange 1514bfb0467fSMichael Lange /* Check for a one-to-all distribution pattern */ 15155f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetPointSF(dm, &sfPoint)); 15165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 1517bfb0467fSMichael Lange if (nroots >= 0) { 1518b9f40539SMichael Lange IS isOriginal; 1519ac04eaf7SToby Isaac PetscInt n, size, nleaves; 1520ac04eaf7SToby Isaac PetscInt *numbering_orig, *numbering_new; 1521367003a6SStefano Zampini 1522b9f40539SMichael Lange /* Get the original point numbering */ 15235f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreatePointNumbering(dm, &isOriginal)); 15245f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateIS(isOriginal, <ogOriginal)); 15255f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetSize(ltogOriginal, &size)); 15265f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingGetBlockIndices(ltogOriginal, (const PetscInt**)&numbering_orig)); 1527b9f40539SMichael Lange /* Convert to positive global numbers */ 1528b9f40539SMichael Lange for (n=0; n<size; n++) {if (numbering_orig[n] < 0) numbering_orig[n] = -(numbering_orig[n]+1);} 1529b9f40539SMichael Lange /* Derive the new local-to-global mapping from the old one */ 15305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sf, NULL, &nleaves, NULL, NULL)); 15315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nleaves, &numbering_new)); 15325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sf, MPIU_INT, numbering_orig, numbering_new,MPI_REPLACE)); 15335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sf, MPIU_INT, numbering_orig, numbering_new,MPI_REPLACE)); 15345f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreate(comm, 1, nleaves, numbering_new, PETSC_OWN_POINTER, <ogMigration)); 15355f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingRestoreIndices(ltogOriginal, (const PetscInt**)&numbering_orig)); 15365f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&isOriginal)); 153715078cd4SMichael Lange } else { 1538bfb0467fSMichael Lange /* One-to-all distribution pattern: We can derive LToG from SF */ 15395f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingCreateSF(sf, 0, <ogMigration)); 154015078cd4SMichael Lange } 15415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-partition_view", &flg)); 1542b9f40539SMichael Lange if (flg) { 15435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(comm, "Point renumbering for DM migration:\n")); 15445f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingView(ltogMigration, NULL)); 1545b9f40539SMichael Lange } 154615078cd4SMichael Lange /* Migrate DM data to target DM */ 15475f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeCones(dm, sf, ltogOriginal, ltogMigration, targetDM)); 15485f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeLabels(dm, sf, targetDM)); 15495f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeCoordinates(dm, sf, targetDM)); 15505f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeSetupTree(dm, sf, ltogOriginal, ltogMigration, targetDM)); 15515f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(<ogOriginal)); 15525f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingDestroy(<ogMigration)); 15535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_Migrate, dm, 0, 0, 0)); 155415078cd4SMichael Lange PetscFunctionReturn(0); 155515078cd4SMichael Lange } 155615078cd4SMichael Lange 15573b8f15a2SMatthew G. Knepley /*@C 155870034214SMatthew G. Knepley DMPlexDistribute - Distributes the mesh and any associated sections. 155970034214SMatthew G. Knepley 1560d083f849SBarry Smith Collective on dm 156170034214SMatthew G. Knepley 1562064ec1f3Sprj- Input Parameters: 156370034214SMatthew G. Knepley + dm - The original DMPlex object 156470034214SMatthew G. Knepley - overlap - The overlap of partitions, 0 is the default 156570034214SMatthew G. Knepley 1566064ec1f3Sprj- Output Parameters: 1567f4ae5380SJed Brown + sf - The PetscSF used for point distribution, or NULL if not needed 1568f4ae5380SJed Brown - dmParallel - The distributed DMPlex object 156970034214SMatthew G. Knepley 1570f4ae5380SJed Brown Note: If the mesh was not distributed, the output dmParallel will be NULL. 157170034214SMatthew G. Knepley 1572b0441da4SMatthew G. Knepley The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function 157370034214SMatthew G. Knepley representation on the mesh. 157470034214SMatthew G. Knepley 157570034214SMatthew G. Knepley Level: intermediate 157670034214SMatthew G. Knepley 1577cb54e036SVaclav Hapla .seealso: DMPlexCreate(), DMSetAdjacency(), DMPlexGetOverlap() 157870034214SMatthew G. Knepley @*/ 157980cf41d5SMatthew G. Knepley PetscErrorCode DMPlexDistribute(DM dm, PetscInt overlap, PetscSF *sf, DM *dmParallel) 158070034214SMatthew G. Knepley { 158170034214SMatthew G. Knepley MPI_Comm comm; 158215078cd4SMichael Lange PetscPartitioner partitioner; 1583f8987ae8SMichael Lange IS cellPart; 1584f8987ae8SMichael Lange PetscSection cellPartSection; 1585cf86098cSMatthew G. Knepley DM dmCoord; 1586f8987ae8SMichael Lange DMLabel lblPartition, lblMigration; 1587874ddda9SLisandro Dalcin PetscSF sfMigration, sfStratified, sfPoint; 158898ba2d7fSLawrence Mitchell PetscBool flg, balance; 1589874ddda9SLisandro Dalcin PetscMPIInt rank, size; 159070034214SMatthew G. Knepley 159170034214SMatthew G. Knepley PetscFunctionBegin; 159270034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1593d5c515a1SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, overlap, 2); 1594d5c515a1SMatthew G. Knepley if (sf) PetscValidPointer(sf,3); 1595d5c515a1SMatthew G. Knepley PetscValidPointer(dmParallel,4); 159670034214SMatthew G. Knepley 15970c86c063SLisandro Dalcin if (sf) *sf = NULL; 15980c86c063SLisandro Dalcin *dmParallel = NULL; 15995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)dm,&comm)); 16005f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 16015f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 16020c86c063SLisandro Dalcin if (size == 1) PetscFunctionReturn(0); 160370034214SMatthew G. Knepley 16045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0)); 160515078cd4SMichael Lange /* Create cell partition */ 16065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_Partition,dm,0,0,0)); 16075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(comm, &cellPartSection)); 16085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetPartitioner(dm, &partitioner)); 16095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerDMPlexPartition(partitioner, dm, NULL, cellPartSection, &cellPart)); 16105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_PartSelf,dm,0,0,0)); 1611f8987ae8SMichael Lange { 1612f8987ae8SMichael Lange /* Convert partition to DMLabel */ 1613825f8a23SLisandro Dalcin IS is; 1614825f8a23SLisandro Dalcin PetscHSetI ht; 1615f8987ae8SMichael Lange const PetscInt *points; 16168e330a33SStefano Zampini PetscInt *iranks; 16178e330a33SStefano Zampini PetscInt pStart, pEnd, proc, npoints, poff = 0, nranks; 1618825f8a23SLisandro Dalcin 16195f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelCreate(PETSC_COMM_SELF, "Point Partition", &lblPartition)); 1620825f8a23SLisandro Dalcin /* Preallocate strata */ 16215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetICreate(&ht)); 16225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1623825f8a23SLisandro Dalcin for (proc = pStart; proc < pEnd; proc++) { 16245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(cellPartSection, proc, &npoints)); 16255f80ce2aSJacob Faibussowitsch if (npoints) CHKERRQ(PetscHSetIAdd(ht, proc)); 1626825f8a23SLisandro Dalcin } 16275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIGetSize(ht, &nranks)); 16285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nranks, &iranks)); 16295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIGetElems(ht, &poff, iranks)); 16305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHSetIDestroy(&ht)); 16315f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelAddStrata(lblPartition, nranks, iranks)); 16325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(iranks)); 1633825f8a23SLisandro Dalcin /* Inline DMPlexPartitionLabelClosure() */ 16345f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(cellPart, &points)); 16355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(cellPartSection, &pStart, &pEnd)); 1636f8987ae8SMichael Lange for (proc = pStart; proc < pEnd; proc++) { 16375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(cellPartSection, proc, &npoints)); 1638825f8a23SLisandro Dalcin if (!npoints) continue; 16395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(cellPartSection, proc, &poff)); 16405f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexClosurePoints_Private(dm, npoints, points+poff, &is)); 16415f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelSetStratumIS(lblPartition, proc, is)); 16425f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is)); 1643f8987ae8SMichael Lange } 16445f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(cellPart, &points)); 1645f8987ae8SMichael Lange } 16465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_PartSelf,dm,0,0,0)); 16476e203dd9SStefano Zampini 16485f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelCreate(PETSC_COMM_SELF, "Point migration", &lblMigration)); 16495f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPartitionLabelInvert(dm, lblPartition, NULL, lblMigration)); 16505f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPartitionLabelCreateSF(dm, lblMigration, &sfMigration)); 16515f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratifyMigrationSF(dm, sfMigration, &sfStratified)); 16525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfMigration)); 165343f7d02bSMichael Lange sfMigration = sfStratified; 16545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetUp(sfMigration)); 16555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_Partition,dm,0,0,0)); 16565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-partition_view", &flg)); 165770034214SMatthew G. Knepley if (flg) { 16585f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelView(lblPartition, PETSC_VIEWER_STDOUT_(comm))); 16595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFView(sfMigration, PETSC_VIEWER_STDOUT_(comm))); 166070034214SMatthew G. Knepley } 1661f8987ae8SMichael Lange 166215078cd4SMichael Lange /* Create non-overlapping parallel DM and migrate internal data */ 16635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreate(comm, dmParallel)); 16645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh")); 16655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMigrate(dm, sfMigration, *dmParallel)); 166670034214SMatthew G. Knepley 1667a157612eSMichael Lange /* Build the point SF without overlap */ 16685f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetPartitionBalance(dm, &balance)); 16695f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetPartitionBalance(*dmParallel, balance)); 16705f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreatePointSF(*dmParallel, sfMigration, PETSC_TRUE, &sfPoint)); 16715f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPointSF(*dmParallel, sfPoint)); 16725f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(*dmParallel, &dmCoord)); 16735f80ce2aSJacob Faibussowitsch if (dmCoord) CHKERRQ(DMSetPointSF(dmCoord, sfPoint)); 16745f80ce2aSJacob Faibussowitsch if (flg) CHKERRQ(PetscSFView(sfPoint, NULL)); 167570034214SMatthew G. Knepley 1676a157612eSMichael Lange if (overlap > 0) { 167715078cd4SMichael Lange DM dmOverlap; 167857f290daSMatthew G. Knepley PetscInt nroots, nleaves, noldleaves, l; 167957f290daSMatthew G. Knepley const PetscInt *oldLeaves; 168057f290daSMatthew G. Knepley PetscSFNode *newRemote, *permRemote; 168115078cd4SMichael Lange const PetscSFNode *oldRemote; 168215078cd4SMichael Lange PetscSF sfOverlap, sfOverlapPoint; 1683524e35f8SStefano Zampini 1684a157612eSMichael Lange /* Add the partition overlap to the distributed DM */ 16855f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeOverlap(*dmParallel, overlap, &sfOverlap, &dmOverlap)); 16865f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(dmParallel)); 1687a157612eSMichael Lange *dmParallel = dmOverlap; 1688c389ea9fSToby Isaac if (flg) { 16895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(comm, "Overlap Migration SF:\n")); 16905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFView(sfOverlap, NULL)); 1691c389ea9fSToby Isaac } 169243331d4aSMichael Lange 1693f8987ae8SMichael Lange /* Re-map the migration SF to establish the full migration pattern */ 16945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sfMigration, &nroots, &noldleaves, &oldLeaves, &oldRemote)); 16955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(sfOverlap, NULL, &nleaves, NULL, NULL)); 16965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nleaves, &newRemote)); 169757f290daSMatthew G. Knepley /* oldRemote: original root point mapping to original leaf point 169857f290daSMatthew G. Knepley newRemote: original leaf point mapping to overlapped leaf point */ 169957f290daSMatthew G. Knepley if (oldLeaves) { 170073e69a6aSMatthew G. Knepley /* After stratification, the migration remotes may not be in root (canonical) order, so we reorder using the leaf numbering */ 17015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(noldleaves, &permRemote)); 170257f290daSMatthew G. Knepley for (l = 0; l < noldleaves; ++l) permRemote[oldLeaves[l]] = oldRemote[l]; 170357f290daSMatthew G. Knepley oldRemote = permRemote; 170457f290daSMatthew G. Knepley } 17055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastBegin(sfOverlap, MPIU_2INT, oldRemote, newRemote,MPI_REPLACE)); 17065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFBcastEnd(sfOverlap, MPIU_2INT, oldRemote, newRemote,MPI_REPLACE)); 17075f80ce2aSJacob Faibussowitsch if (oldLeaves) CHKERRQ(PetscFree(oldRemote)); 17085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreate(comm, &sfOverlapPoint)); 17095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraph(sfOverlapPoint, nroots, nleaves, NULL, PETSC_OWN_POINTER, newRemote, PETSC_OWN_POINTER)); 17105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfOverlap)); 17115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfMigration)); 171215078cd4SMichael Lange sfMigration = sfOverlapPoint; 1713c389ea9fSToby Isaac } 1714bf5244c7SMatthew G. Knepley /* Cleanup Partition */ 17155f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelDestroy(&lblPartition)); 17165f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelDestroy(&lblMigration)); 17175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&cellPartSection)); 17185f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&cellPart)); 171945480ffeSMatthew G. Knepley /* Copy discretization */ 17205f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyDisc(dm, *dmParallel)); 172166fe0bfeSMatthew G. Knepley /* Create sfNatural */ 172266fe0bfeSMatthew G. Knepley if (dm->useNatural) { 172366fe0bfeSMatthew G. Knepley PetscSection section; 172466fe0bfeSMatthew G. Knepley 17255f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(dm, §ion)); 17265f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateGlobalToNaturalSF(*dmParallel, section, sfMigration, &(*dmParallel)->sfNatural)); 17275f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUseNatural(*dmParallel, PETSC_TRUE)); 172866fe0bfeSMatthew G. Knepley } 17295f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopy_Internal(dm, PETSC_TRUE, *dmParallel)); 1730721cbd76SMatthew G. Knepley /* Cleanup */ 1731f8987ae8SMichael Lange if (sf) {*sf = sfMigration;} 17325f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSFDestroy(&sfMigration)); 17335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfPoint)); 17345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0)); 173570034214SMatthew G. Knepley PetscFunctionReturn(0); 173670034214SMatthew G. Knepley } 1737a157612eSMichael Lange 1738a157612eSMichael Lange /*@C 173924cc2ca5SMatthew G. Knepley DMPlexDistributeOverlap - Add partition overlap to a distributed non-overlapping DM. 1740a157612eSMichael Lange 1741d083f849SBarry Smith Collective on dm 1742a157612eSMichael Lange 1743064ec1f3Sprj- Input Parameters: 1744064ec1f3Sprj- + dm - The non-overlapping distributed DMPlex object 174557fe9a49SVaclav Hapla - overlap - The overlap of partitions (the same on all ranks) 1746a157612eSMichael Lange 1747064ec1f3Sprj- Output Parameters: 1748a157612eSMichael Lange + sf - The PetscSF used for point distribution 1749a157612eSMichael Lange - dmOverlap - The overlapping distributed DMPlex object, or NULL 1750a157612eSMichael Lange 1751dccdeccaSVaclav Hapla Notes: 1752dccdeccaSVaclav Hapla If the mesh was not distributed, the return value is NULL. 1753a157612eSMichael Lange 1754b0441da4SMatthew G. Knepley The user can control the definition of adjacency for the mesh using DMSetAdjacency(). They should choose the combination appropriate for the function 1755a157612eSMichael Lange representation on the mesh. 1756a157612eSMichael Lange 1757dccdeccaSVaclav Hapla Level: advanced 1758a157612eSMichael Lange 1759cb54e036SVaclav Hapla .seealso: DMPlexCreate(), DMSetAdjacency(), DMPlexDistribute(), DMPlexCreateOverlapLabel(), DMPlexGetOverlap() 1760a157612eSMichael Lange @*/ 1761b9f40539SMichael Lange PetscErrorCode DMPlexDistributeOverlap(DM dm, PetscInt overlap, PetscSF *sf, DM *dmOverlap) 1762a157612eSMichael Lange { 1763a157612eSMichael Lange MPI_Comm comm; 17643567eaeeSMatthew G. Knepley PetscMPIInt size, rank; 1765a157612eSMichael Lange PetscSection rootSection, leafSection; 1766a157612eSMichael Lange IS rootrank, leafrank; 1767cf86098cSMatthew G. Knepley DM dmCoord; 1768a9f1d5b2SMichael Lange DMLabel lblOverlap; 1769f5bf2dbfSMichael Lange PetscSF sfOverlap, sfStratified, sfPoint; 1770a157612eSMichael Lange 1771a157612eSMichael Lange PetscFunctionBegin; 1772a157612eSMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 177357fe9a49SVaclav Hapla PetscValidLogicalCollectiveInt(dm, overlap, 2); 1774a157612eSMichael Lange if (sf) PetscValidPointer(sf, 3); 1775a157612eSMichael Lange PetscValidPointer(dmOverlap, 4); 1776a157612eSMichael Lange 17770c86c063SLisandro Dalcin if (sf) *sf = NULL; 17780c86c063SLisandro Dalcin *dmOverlap = NULL; 17795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)dm,&comm)); 17805f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 17815f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 17820c86c063SLisandro Dalcin if (size == 1) PetscFunctionReturn(0); 1783a157612eSMichael Lange 17845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 1785a157612eSMichael Lange /* Compute point overlap with neighbouring processes on the distributed DM */ 17865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(DMPLEX_Partition,dm,0,0,0)); 17875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(comm, &rootSection)); 17885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionCreate(comm, &leafSection)); 17895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistributeOwnership(dm, rootSection, &rootrank, leafSection, &leafrank)); 17905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateOverlapLabel(dm, overlap, rootSection, rootrank, leafSection, leafrank, &lblOverlap)); 1791a9f1d5b2SMichael Lange /* Convert overlap label to stratified migration SF */ 17925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexPartitionLabelCreateSF(dm, lblOverlap, &sfOverlap)); 17935f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratifyMigrationSF(dm, sfOverlap, &sfStratified)); 17945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfOverlap)); 1795a9f1d5b2SMichael Lange sfOverlap = sfStratified; 17965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) sfOverlap, "Overlap SF")); 17975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetFromOptions(sfOverlap)); 1798a9f1d5b2SMichael Lange 17995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&rootSection)); 18005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionDestroy(&leafSection)); 18015f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&rootrank)); 18025f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&leafrank)); 18035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_Partition,dm,0,0,0)); 1804a157612eSMichael Lange 1805a157612eSMichael Lange /* Build the overlapping DM */ 18065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreate(comm, dmOverlap)); 18075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) *dmOverlap, "Parallel Mesh")); 18085f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMigrate(dm, sfOverlap, *dmOverlap)); 1809cb54e036SVaclav Hapla /* Store the overlap in the new DM */ 1810cb54e036SVaclav Hapla ((DM_Plex*)(*dmOverlap)->data)->overlap = overlap + ((DM_Plex*)dm->data)->overlap; 1811f5bf2dbfSMichael Lange /* Build the new point SF */ 18125f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreatePointSF(*dmOverlap, sfOverlap, PETSC_FALSE, &sfPoint)); 18135f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPointSF(*dmOverlap, sfPoint)); 18145f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(*dmOverlap, &dmCoord)); 18155f80ce2aSJacob Faibussowitsch if (dmCoord) CHKERRQ(DMSetPointSF(dmCoord, sfPoint)); 18165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfPoint)); 1817a157612eSMichael Lange /* Cleanup overlap partition */ 18185f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelDestroy(&lblOverlap)); 1819a9f1d5b2SMichael Lange if (sf) *sf = sfOverlap; 18205f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscSFDestroy(&sfOverlap)); 18215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(DMPLEX_DistributeOverlap, dm, 0, 0, 0)); 1822a157612eSMichael Lange PetscFunctionReturn(0); 1823a157612eSMichael Lange } 18246462276dSToby Isaac 1825cb54e036SVaclav Hapla PetscErrorCode DMPlexGetOverlap_Plex(DM dm, PetscInt *overlap) 1826cb54e036SVaclav Hapla { 1827cb54e036SVaclav Hapla DM_Plex *mesh = (DM_Plex*) dm->data; 1828cb54e036SVaclav Hapla 1829cb54e036SVaclav Hapla PetscFunctionBegin; 1830cb54e036SVaclav Hapla *overlap = mesh->overlap; 1831cb54e036SVaclav Hapla PetscFunctionReturn(0); 1832cb54e036SVaclav Hapla } 1833cb54e036SVaclav Hapla 1834cb54e036SVaclav Hapla /*@ 1835cb54e036SVaclav Hapla DMPlexGetOverlap - Get the DMPlex partition overlap. 1836cb54e036SVaclav Hapla 1837cb54e036SVaclav Hapla Not collective 1838cb54e036SVaclav Hapla 1839cb54e036SVaclav Hapla Input Parameter: 1840cb54e036SVaclav Hapla . dm - The DM 1841cb54e036SVaclav Hapla 1842064ec1f3Sprj- Output Parameter: 1843cb54e036SVaclav Hapla . overlap - The overlap of this DM 1844cb54e036SVaclav Hapla 1845cb54e036SVaclav Hapla Level: intermediate 1846cb54e036SVaclav Hapla 1847cb54e036SVaclav Hapla .seealso: DMPlexDistribute(), DMPlexDistributeOverlap(), DMPlexCreateOverlapLabel() 1848cb54e036SVaclav Hapla @*/ 1849cb54e036SVaclav Hapla PetscErrorCode DMPlexGetOverlap(DM dm, PetscInt *overlap) 1850cb54e036SVaclav Hapla { 1851cb54e036SVaclav Hapla PetscFunctionBegin; 1852cb54e036SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 18535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscUseMethod(dm,"DMPlexGetOverlap_C",(DM,PetscInt*),(dm,overlap))); 1854cb54e036SVaclav Hapla PetscFunctionReturn(0); 1855cb54e036SVaclav Hapla } 1856cb54e036SVaclav Hapla 1857e600fa54SMatthew G. Knepley PetscErrorCode DMPlexDistributeSetDefault_Plex(DM dm, PetscBool dist) 1858e600fa54SMatthew G. Knepley { 1859e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 1860e600fa54SMatthew G. Knepley 1861e600fa54SMatthew G. Knepley PetscFunctionBegin; 1862e600fa54SMatthew G. Knepley mesh->distDefault = dist; 1863e600fa54SMatthew G. Knepley PetscFunctionReturn(0); 1864e600fa54SMatthew G. Knepley } 1865e600fa54SMatthew G. Knepley 1866e600fa54SMatthew G. Knepley /*@ 1867e600fa54SMatthew G. Knepley DMPlexDistributeSetDefault - Set flag indicating whether the DM should be distributed by default 1868e600fa54SMatthew G. Knepley 1869e600fa54SMatthew G. Knepley Logically collective 1870e600fa54SMatthew G. Knepley 1871e600fa54SMatthew G. Knepley Input Parameters: 1872e600fa54SMatthew G. Knepley + dm - The DM 1873e600fa54SMatthew G. Knepley - dist - Flag for distribution 1874e600fa54SMatthew G. Knepley 1875e600fa54SMatthew G. Knepley Level: intermediate 1876e600fa54SMatthew G. Knepley 1877e600fa54SMatthew G. Knepley .seealso: DMDistributeGetDefault(), DMPlexDistribute() 1878e600fa54SMatthew G. Knepley @*/ 1879e600fa54SMatthew G. Knepley PetscErrorCode DMPlexDistributeSetDefault(DM dm, PetscBool dist) 1880e600fa54SMatthew G. Knepley { 1881e600fa54SMatthew G. Knepley PetscFunctionBegin; 1882e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1883e600fa54SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, dist, 2); 18845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTryMethod(dm,"DMPlexDistributeSetDefault_C",(DM,PetscBool),(dm,dist))); 1885e600fa54SMatthew G. Knepley PetscFunctionReturn(0); 1886e600fa54SMatthew G. Knepley } 1887e600fa54SMatthew G. Knepley 1888e600fa54SMatthew G. Knepley PetscErrorCode DMPlexDistributeGetDefault_Plex(DM dm, PetscBool *dist) 1889e600fa54SMatthew G. Knepley { 1890e600fa54SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 1891e600fa54SMatthew G. Knepley 1892e600fa54SMatthew G. Knepley PetscFunctionBegin; 1893e600fa54SMatthew G. Knepley *dist = mesh->distDefault; 1894e600fa54SMatthew G. Knepley PetscFunctionReturn(0); 1895e600fa54SMatthew G. Knepley } 1896e600fa54SMatthew G. Knepley 1897e600fa54SMatthew G. Knepley /*@ 1898e600fa54SMatthew G. Knepley DMPlexDistributeGetDefault - Get flag indicating whether the DM should be distributed by default 1899e600fa54SMatthew G. Knepley 1900e600fa54SMatthew G. Knepley Not collective 1901e600fa54SMatthew G. Knepley 1902e600fa54SMatthew G. Knepley Input Parameter: 1903e600fa54SMatthew G. Knepley . dm - The DM 1904e600fa54SMatthew G. Knepley 1905e600fa54SMatthew G. Knepley Output Parameter: 1906e600fa54SMatthew G. Knepley . dist - Flag for distribution 1907e600fa54SMatthew G. Knepley 1908e600fa54SMatthew G. Knepley Level: intermediate 1909e600fa54SMatthew G. Knepley 1910e600fa54SMatthew G. Knepley .seealso: DMDistributeSetDefault(), DMPlexDistribute() 1911e600fa54SMatthew G. Knepley @*/ 1912e600fa54SMatthew G. Knepley PetscErrorCode DMPlexDistributeGetDefault(DM dm, PetscBool *dist) 1913e600fa54SMatthew G. Knepley { 1914e600fa54SMatthew G. Knepley PetscFunctionBegin; 1915e600fa54SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1916e600fa54SMatthew G. Knepley PetscValidBoolPointer(dist, 2); 19175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscUseMethod(dm,"DMPlexDistributeGetDefault_C",(DM,PetscBool*),(dm,dist))); 1918e600fa54SMatthew G. Knepley PetscFunctionReturn(0); 1919e600fa54SMatthew G. Knepley } 1920e600fa54SMatthew G. Knepley 19216462276dSToby Isaac /*@C 19226462276dSToby Isaac DMPlexGetGatherDM - Get a copy of the DMPlex that gathers all points on the 19236462276dSToby Isaac root process of the original's communicator. 19246462276dSToby Isaac 1925d083f849SBarry Smith Collective on dm 192683655b49SVáclav Hapla 1927064ec1f3Sprj- Input Parameter: 19286462276dSToby Isaac . dm - the original DMPlex object 19296462276dSToby Isaac 19306462276dSToby Isaac Output Parameters: 1931a13df41bSStefano Zampini + sf - the PetscSF used for point distribution (optional) 1932a13df41bSStefano Zampini - gatherMesh - the gathered DM object, or NULL 19336462276dSToby Isaac 19346462276dSToby Isaac Level: intermediate 19356462276dSToby Isaac 19366462276dSToby Isaac .seealso: DMPlexDistribute(), DMPlexGetRedundantDM() 19376462276dSToby Isaac @*/ 1938a13df41bSStefano Zampini PetscErrorCode DMPlexGetGatherDM(DM dm, PetscSF *sf, DM *gatherMesh) 19396462276dSToby Isaac { 19406462276dSToby Isaac MPI_Comm comm; 19416462276dSToby Isaac PetscMPIInt size; 19426462276dSToby Isaac PetscPartitioner oldPart, gatherPart; 19436462276dSToby Isaac 19446462276dSToby Isaac PetscFunctionBegin; 19456462276dSToby Isaac PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1946064a246eSJacob Faibussowitsch PetscValidPointer(gatherMesh,3); 19470c86c063SLisandro Dalcin *gatherMesh = NULL; 1948a13df41bSStefano Zampini if (sf) *sf = NULL; 19496462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 19505f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm,&size)); 19516462276dSToby Isaac if (size == 1) PetscFunctionReturn(0); 19525f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetPartitioner(dm,&oldPart)); 19535f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)oldPart)); 19545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerCreate(comm,&gatherPart)); 19555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerSetType(gatherPart,PETSCPARTITIONERGATHER)); 19565f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetPartitioner(dm,gatherPart)); 19575f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexDistribute(dm,0,sf,gatherMesh)); 1958a13df41bSStefano Zampini 19595f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSetPartitioner(dm,oldPart)); 19605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerDestroy(&gatherPart)); 19615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPartitionerDestroy(&oldPart)); 19626462276dSToby Isaac PetscFunctionReturn(0); 19636462276dSToby Isaac } 19646462276dSToby Isaac 19656462276dSToby Isaac /*@C 19666462276dSToby Isaac DMPlexGetRedundantDM - Get a copy of the DMPlex that is completely copied on each process. 19676462276dSToby Isaac 1968d083f849SBarry Smith Collective on dm 196983655b49SVáclav Hapla 1970064ec1f3Sprj- Input Parameter: 19716462276dSToby Isaac . dm - the original DMPlex object 19726462276dSToby Isaac 19736462276dSToby Isaac Output Parameters: 1974a13df41bSStefano Zampini + sf - the PetscSF used for point distribution (optional) 1975a13df41bSStefano Zampini - redundantMesh - the redundant DM object, or NULL 19766462276dSToby Isaac 19776462276dSToby Isaac Level: intermediate 19786462276dSToby Isaac 19796462276dSToby Isaac .seealso: DMPlexDistribute(), DMPlexGetGatherDM() 19806462276dSToby Isaac @*/ 1981a13df41bSStefano Zampini PetscErrorCode DMPlexGetRedundantDM(DM dm, PetscSF *sf, DM *redundantMesh) 19826462276dSToby Isaac { 19836462276dSToby Isaac MPI_Comm comm; 19846462276dSToby Isaac PetscMPIInt size, rank; 19856462276dSToby Isaac PetscInt pStart, pEnd, p; 19866462276dSToby Isaac PetscInt numPoints = -1; 1987a13df41bSStefano Zampini PetscSF migrationSF, sfPoint, gatherSF; 19886462276dSToby Isaac DM gatherDM, dmCoord; 19896462276dSToby Isaac PetscSFNode *points; 19906462276dSToby Isaac 19916462276dSToby Isaac PetscFunctionBegin; 19926462276dSToby Isaac PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1993064a246eSJacob Faibussowitsch PetscValidPointer(redundantMesh,3); 19940c86c063SLisandro Dalcin *redundantMesh = NULL; 19956462276dSToby Isaac comm = PetscObjectComm((PetscObject)dm); 19965f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm,&size)); 199768dbc166SMatthew G. Knepley if (size == 1) { 19985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) dm)); 199968dbc166SMatthew G. Knepley *redundantMesh = dm; 2000a13df41bSStefano Zampini if (sf) *sf = NULL; 200168dbc166SMatthew G. Knepley PetscFunctionReturn(0); 200268dbc166SMatthew G. Knepley } 20035f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetGatherDM(dm,&gatherSF,&gatherDM)); 20046462276dSToby Isaac if (!gatherDM) PetscFunctionReturn(0); 20055f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm,&rank)); 20065f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(gatherDM,&pStart,&pEnd)); 20076462276dSToby Isaac numPoints = pEnd - pStart; 20085f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Bcast(&numPoints,1,MPIU_INT,0,comm)); 20095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numPoints,&points)); 20105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCreate(comm,&migrationSF)); 20116462276dSToby Isaac for (p = 0; p < numPoints; p++) { 20126462276dSToby Isaac points[p].index = p; 20136462276dSToby Isaac points[p].rank = 0; 20146462276dSToby Isaac } 20155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFSetGraph(migrationSF,pEnd-pStart,numPoints,NULL,PETSC_OWN_POINTER,points,PETSC_OWN_POINTER)); 20165f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreate(comm, redundantMesh)); 20175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) *redundantMesh, "Redundant Mesh")); 20185f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMigrate(gatherDM, migrationSF, *redundantMesh)); 20195f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreatePointSF(*redundantMesh, migrationSF, PETSC_FALSE, &sfPoint)); 20205f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetPointSF(*redundantMesh, sfPoint)); 20215f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(*redundantMesh, &dmCoord)); 20225f80ce2aSJacob Faibussowitsch if (dmCoord) CHKERRQ(DMSetPointSF(dmCoord, sfPoint)); 20235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&sfPoint)); 2024a13df41bSStefano Zampini if (sf) { 2025a13df41bSStefano Zampini PetscSF tsf; 2026a13df41bSStefano Zampini 20275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFCompose(gatherSF,migrationSF,&tsf)); 20285f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexStratifyMigrationSF(dm, tsf, sf)); 20295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&tsf)); 2030a13df41bSStefano Zampini } 20315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&migrationSF)); 20325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&gatherSF)); 20335f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&gatherDM)); 20345f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyDisc(dm, *redundantMesh)); 20355f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopy_Internal(dm, PETSC_TRUE, *redundantMesh)); 20366462276dSToby Isaac PetscFunctionReturn(0); 20376462276dSToby Isaac } 20385fa78c88SVaclav Hapla 20395fa78c88SVaclav Hapla /*@ 20405fa78c88SVaclav Hapla DMPlexIsDistributed - Find out whether this DM is distributed, i.e. more than one rank owns some points. 20415fa78c88SVaclav Hapla 20425fa78c88SVaclav Hapla Collective 20435fa78c88SVaclav Hapla 20445fa78c88SVaclav Hapla Input Parameter: 20455fa78c88SVaclav Hapla . dm - The DM object 20465fa78c88SVaclav Hapla 20475fa78c88SVaclav Hapla Output Parameter: 20485fa78c88SVaclav Hapla . distributed - Flag whether the DM is distributed 20495fa78c88SVaclav Hapla 20505fa78c88SVaclav Hapla Level: intermediate 20515fa78c88SVaclav Hapla 20525fa78c88SVaclav Hapla Notes: 20535fa78c88SVaclav Hapla This currently finds out whether at least two ranks have any DAG points. 20545fa78c88SVaclav Hapla This involves MPI_Allreduce() with one integer. 20555fa78c88SVaclav Hapla The result is currently not stashed so every call to this routine involves this global communication. 20565fa78c88SVaclav Hapla 20575fa78c88SVaclav Hapla .seealso: DMPlexDistribute(), DMPlexGetOverlap(), DMPlexIsInterpolated() 20585fa78c88SVaclav Hapla @*/ 20595fa78c88SVaclav Hapla PetscErrorCode DMPlexIsDistributed(DM dm, PetscBool *distributed) 20605fa78c88SVaclav Hapla { 20615fa78c88SVaclav Hapla PetscInt pStart, pEnd, count; 20625fa78c88SVaclav Hapla MPI_Comm comm; 206335d70e31SStefano Zampini PetscMPIInt size; 20645fa78c88SVaclav Hapla 20655fa78c88SVaclav Hapla PetscFunctionBegin; 20665fa78c88SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20675fa78c88SVaclav Hapla PetscValidPointer(distributed,2); 20685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)dm,&comm)); 20695f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm,&size)); 207035d70e31SStefano Zampini if (size == 1) { *distributed = PETSC_FALSE; PetscFunctionReturn(0); } 20715f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd)); 207235d70e31SStefano Zampini count = (pEnd - pStart) > 0 ? 1 : 0; 20735f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allreduce(MPI_IN_PLACE, &count, 1, MPIU_INT, MPI_SUM, comm)); 20745fa78c88SVaclav Hapla *distributed = count > 1 ? PETSC_TRUE : PETSC_FALSE; 20755fa78c88SVaclav Hapla PetscFunctionReturn(0); 20765fa78c88SVaclav Hapla } 2077