170034214SMatthew G. Knepley #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 270034214SMatthew G. Knepley #include <petscsf.h> 370034214SMatthew G. Knepley 470034214SMatthew G. Knepley #undef __FUNCT__ 570034214SMatthew G. Knepley #define __FUNCT__ "DMPlexSetAdjacencyUseCone" 670034214SMatthew G. Knepley /*@ 770034214SMatthew G. Knepley DMPlexSetAdjacencyUseCone - Define adjacency in the mesh using either the cone or the support first 870034214SMatthew G. Knepley 970034214SMatthew G. Knepley Input Parameters: 1070034214SMatthew G. Knepley + dm - The DM object 1170034214SMatthew G. Knepley - useCone - Flag to use the cone first 1270034214SMatthew G. Knepley 1370034214SMatthew G. Knepley Level: intermediate 1470034214SMatthew G. Knepley 1570034214SMatthew G. Knepley Notes: 1670034214SMatthew G. Knepley $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 1770034214SMatthew G. Knepley $ FVM: Two points p and q are adjacent if q \in star(cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 1870034214SMatthew G. Knepley $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 1970034214SMatthew G. Knepley 2070034214SMatthew G. Knepley .seealso: DMPlexGetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure(), DMPlexGetAdjacencyUseClosure(), DMPlexDistribute(), DMPlexPreallocateOperator() 2170034214SMatthew G. Knepley @*/ 2270034214SMatthew G. Knepley PetscErrorCode DMPlexSetAdjacencyUseCone(DM dm, PetscBool useCone) 2370034214SMatthew G. Knepley { 2470034214SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 2570034214SMatthew G. Knepley 2670034214SMatthew G. Knepley PetscFunctionBegin; 2770034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2870034214SMatthew G. Knepley mesh->useCone = useCone; 2970034214SMatthew G. Knepley PetscFunctionReturn(0); 3070034214SMatthew G. Knepley } 3170034214SMatthew G. Knepley 3270034214SMatthew G. Knepley #undef __FUNCT__ 3370034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacencyUseCone" 3470034214SMatthew G. Knepley /*@ 3570034214SMatthew G. Knepley DMPlexGetAdjacencyUseCone - Query whether adjacency in the mesh uses the cone or the support first 3670034214SMatthew G. Knepley 3770034214SMatthew G. Knepley Input Parameter: 3870034214SMatthew G. Knepley . dm - The DM object 3970034214SMatthew G. Knepley 4070034214SMatthew G. Knepley Output Parameter: 4170034214SMatthew G. Knepley . useCone - Flag to use the cone first 4270034214SMatthew G. Knepley 4370034214SMatthew G. Knepley Level: intermediate 4470034214SMatthew G. Knepley 4570034214SMatthew G. Knepley Notes: 4670034214SMatthew G. Knepley $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 4770034214SMatthew G. Knepley $ FVM: Two points p and q are adjacent if q \in star(cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 4870034214SMatthew G. Knepley $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 4970034214SMatthew G. Knepley 5070034214SMatthew G. Knepley .seealso: DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure(), DMPlexGetAdjacencyUseClosure(), DMPlexDistribute(), DMPlexPreallocateOperator() 5170034214SMatthew G. Knepley @*/ 5270034214SMatthew G. Knepley PetscErrorCode DMPlexGetAdjacencyUseCone(DM dm, PetscBool *useCone) 5370034214SMatthew G. Knepley { 5470034214SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 5570034214SMatthew G. Knepley 5670034214SMatthew G. Knepley PetscFunctionBegin; 5770034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5870034214SMatthew G. Knepley PetscValidIntPointer(useCone, 2); 5970034214SMatthew G. Knepley *useCone = mesh->useCone; 6070034214SMatthew G. Knepley PetscFunctionReturn(0); 6170034214SMatthew G. Knepley } 6270034214SMatthew G. Knepley 6370034214SMatthew G. Knepley #undef __FUNCT__ 6470034214SMatthew G. Knepley #define __FUNCT__ "DMPlexSetAdjacencyUseClosure" 6570034214SMatthew G. Knepley /*@ 6670034214SMatthew G. Knepley DMPlexSetAdjacencyUseClosure - Define adjacency in the mesh using the transitive closure 6770034214SMatthew G. Knepley 6870034214SMatthew G. Knepley Input Parameters: 6970034214SMatthew G. Knepley + dm - The DM object 7070034214SMatthew G. Knepley - useClosure - Flag to use the closure 7170034214SMatthew G. Knepley 7270034214SMatthew G. Knepley Level: intermediate 7370034214SMatthew G. Knepley 7470034214SMatthew G. Knepley Notes: 7570034214SMatthew G. Knepley $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 7670034214SMatthew G. Knepley $ FVM: Two points p and q are adjacent if q \in star(cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 7770034214SMatthew G. Knepley $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 7870034214SMatthew G. Knepley 7970034214SMatthew G. Knepley .seealso: DMPlexGetAdjacencyUseClosure(), DMPlexSetAdjacencyUseCone(), DMPlexGetAdjacencyUseCone(), DMPlexDistribute(), DMPlexPreallocateOperator() 8070034214SMatthew G. Knepley @*/ 8170034214SMatthew G. Knepley PetscErrorCode DMPlexSetAdjacencyUseClosure(DM dm, PetscBool useClosure) 8270034214SMatthew G. Knepley { 8370034214SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 8470034214SMatthew G. Knepley 8570034214SMatthew G. Knepley PetscFunctionBegin; 8670034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8770034214SMatthew G. Knepley mesh->useClosure = useClosure; 8870034214SMatthew G. Knepley PetscFunctionReturn(0); 8970034214SMatthew G. Knepley } 9070034214SMatthew G. Knepley 9170034214SMatthew G. Knepley #undef __FUNCT__ 9270034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacencyUseClosure" 9370034214SMatthew G. Knepley /*@ 9470034214SMatthew G. Knepley DMPlexGetAdjacencyUseClosure - Query whether adjacency in the mesh uses the transitive closure 9570034214SMatthew G. Knepley 9670034214SMatthew G. Knepley Input Parameter: 9770034214SMatthew G. Knepley . dm - The DM object 9870034214SMatthew G. Knepley 9970034214SMatthew G. Knepley Output Parameter: 10070034214SMatthew G. Knepley . useClosure - Flag to use the closure 10170034214SMatthew G. Knepley 10270034214SMatthew G. Knepley Level: intermediate 10370034214SMatthew G. Knepley 10470034214SMatthew G. Knepley Notes: 10570034214SMatthew G. Knepley $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 10670034214SMatthew G. Knepley $ FVM: Two points p and q are adjacent if q \in star(cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 10770034214SMatthew G. Knepley $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 10870034214SMatthew G. Knepley 10970034214SMatthew G. Knepley .seealso: DMPlexSetAdjacencyUseClosure(), DMPlexSetAdjacencyUseCone(), DMPlexGetAdjacencyUseCone(), DMPlexDistribute(), DMPlexPreallocateOperator() 11070034214SMatthew G. Knepley @*/ 11170034214SMatthew G. Knepley PetscErrorCode DMPlexGetAdjacencyUseClosure(DM dm, PetscBool *useClosure) 11270034214SMatthew G. Knepley { 11370034214SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 11470034214SMatthew G. Knepley 11570034214SMatthew G. Knepley PetscFunctionBegin; 11670034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 11770034214SMatthew G. Knepley PetscValidIntPointer(useClosure, 2); 11870034214SMatthew G. Knepley *useClosure = mesh->useClosure; 11970034214SMatthew G. Knepley PetscFunctionReturn(0); 12070034214SMatthew G. Knepley } 12170034214SMatthew G. Knepley 12270034214SMatthew G. Knepley #undef __FUNCT__ 123a17985deSToby Isaac #define __FUNCT__ "DMPlexSetAdjacencyUseAnchors" 1248b0b4c70SToby Isaac /*@ 125a17985deSToby Isaac DMPlexSetAdjacencyUseAnchors - Define adjacency in the mesh using the point-to-point constraints. 1268b0b4c70SToby Isaac 1278b0b4c70SToby Isaac Input Parameters: 1288b0b4c70SToby Isaac + dm - The DM object 1295b317d89SToby 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. 1308b0b4c70SToby Isaac 1318b0b4c70SToby Isaac Level: intermediate 1328b0b4c70SToby Isaac 133a17985deSToby Isaac .seealso: DMPlexGetAdjacencyUseClosure(), DMPlexSetAdjacencyUseCone(), DMPlexGetAdjacencyUseCone(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexSetAnchors() 1348b0b4c70SToby Isaac @*/ 1355b317d89SToby Isaac PetscErrorCode DMPlexSetAdjacencyUseAnchors(DM dm, PetscBool useAnchors) 1368b0b4c70SToby Isaac { 1378b0b4c70SToby Isaac DM_Plex *mesh = (DM_Plex *) dm->data; 1388b0b4c70SToby Isaac 1398b0b4c70SToby Isaac PetscFunctionBegin; 1408b0b4c70SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1415b317d89SToby Isaac mesh->useAnchors = useAnchors; 1428b0b4c70SToby Isaac PetscFunctionReturn(0); 1438b0b4c70SToby Isaac } 1448b0b4c70SToby Isaac 1458b0b4c70SToby Isaac #undef __FUNCT__ 146a17985deSToby Isaac #define __FUNCT__ "DMPlexGetAdjacencyUseAnchors" 1478b0b4c70SToby Isaac /*@ 148a17985deSToby Isaac DMPlexGetAdjacencyUseAnchors - Query whether adjacency in the mesh uses the point-to-point constraints. 1498b0b4c70SToby Isaac 1508b0b4c70SToby Isaac Input Parameter: 1518b0b4c70SToby Isaac . dm - The DM object 1528b0b4c70SToby Isaac 1538b0b4c70SToby Isaac Output Parameter: 1545b317d89SToby 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. 1558b0b4c70SToby Isaac 1568b0b4c70SToby Isaac Level: intermediate 1578b0b4c70SToby Isaac 158a17985deSToby Isaac .seealso: DMPlexSetAdjacencyUseAnchors(), DMPlexSetAdjacencyUseCone(), DMPlexGetAdjacencyUseCone(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexSetAnchors() 1598b0b4c70SToby Isaac @*/ 1605b317d89SToby Isaac PetscErrorCode DMPlexGetAdjacencyUseAnchors(DM dm, PetscBool *useAnchors) 1618b0b4c70SToby Isaac { 1628b0b4c70SToby Isaac DM_Plex *mesh = (DM_Plex *) dm->data; 1638b0b4c70SToby Isaac 1648b0b4c70SToby Isaac PetscFunctionBegin; 1658b0b4c70SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1665b317d89SToby Isaac PetscValidIntPointer(useAnchors, 2); 1675b317d89SToby Isaac *useAnchors = mesh->useAnchors; 1688b0b4c70SToby Isaac PetscFunctionReturn(0); 1698b0b4c70SToby Isaac } 1708b0b4c70SToby Isaac 1718b0b4c70SToby Isaac #undef __FUNCT__ 17270034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacency_Cone_Internal" 17370034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Cone_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[]) 17470034214SMatthew G. Knepley { 17570034214SMatthew G. Knepley const PetscInt *cone = NULL; 17670034214SMatthew G. Knepley PetscInt numAdj = 0, maxAdjSize = *adjSize, coneSize, c; 17770034214SMatthew G. Knepley PetscErrorCode ierr; 17870034214SMatthew G. Knepley 17970034214SMatthew G. Knepley PetscFunctionBeginHot; 18070034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 18170034214SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 18270034214SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 18370034214SMatthew G. Knepley const PetscInt *support = NULL; 18470034214SMatthew G. Knepley PetscInt supportSize, s, q; 18570034214SMatthew G. Knepley 18670034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 18770034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 18870034214SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 18970034214SMatthew G. Knepley for (q = 0; q < numAdj || (adj[numAdj++] = support[s],0); ++q) { 19070034214SMatthew G. Knepley if (support[s] == adj[q]) break; 19170034214SMatthew G. Knepley } 19270034214SMatthew G. Knepley if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 19370034214SMatthew G. Knepley } 19470034214SMatthew G. Knepley } 19570034214SMatthew G. Knepley *adjSize = numAdj; 19670034214SMatthew G. Knepley PetscFunctionReturn(0); 19770034214SMatthew G. Knepley } 19870034214SMatthew G. Knepley 19970034214SMatthew G. Knepley #undef __FUNCT__ 20070034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacency_Support_Internal" 20170034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Support_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[]) 20270034214SMatthew G. Knepley { 20370034214SMatthew G. Knepley const PetscInt *support = NULL; 20470034214SMatthew G. Knepley PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 20570034214SMatthew G. Knepley PetscErrorCode ierr; 20670034214SMatthew G. Knepley 20770034214SMatthew G. Knepley PetscFunctionBeginHot; 20870034214SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 20970034214SMatthew G. Knepley ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 21070034214SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 21170034214SMatthew G. Knepley const PetscInt *cone = NULL; 21270034214SMatthew G. Knepley PetscInt coneSize, c, q; 21370034214SMatthew G. Knepley 21470034214SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 21570034214SMatthew G. Knepley ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 21670034214SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 21770034214SMatthew G. Knepley for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 21870034214SMatthew G. Knepley if (cone[c] == adj[q]) break; 21970034214SMatthew G. Knepley } 22070034214SMatthew G. Knepley if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 22170034214SMatthew G. Knepley } 22270034214SMatthew G. Knepley } 22370034214SMatthew G. Knepley *adjSize = numAdj; 22470034214SMatthew G. Knepley PetscFunctionReturn(0); 22570034214SMatthew G. Knepley } 22670034214SMatthew G. Knepley 22770034214SMatthew G. Knepley #undef __FUNCT__ 22870034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacency_Transitive_Internal" 22970034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Transitive_Internal(DM dm, PetscInt p, PetscBool useClosure, PetscInt *adjSize, PetscInt adj[]) 23070034214SMatthew G. Knepley { 23170034214SMatthew G. Knepley PetscInt *star = NULL; 23270034214SMatthew G. Knepley PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 23370034214SMatthew G. Knepley PetscErrorCode ierr; 23470034214SMatthew G. Knepley 23570034214SMatthew G. Knepley PetscFunctionBeginHot; 23670034214SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, &star);CHKERRQ(ierr); 23770034214SMatthew G. Knepley for (s = 0; s < starSize*2; s += 2) { 23870034214SMatthew G. Knepley const PetscInt *closure = NULL; 23970034214SMatthew G. Knepley PetscInt closureSize, c, q; 24070034214SMatthew G. Knepley 24170034214SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 24270034214SMatthew G. Knepley for (c = 0; c < closureSize*2; c += 2) { 24370034214SMatthew G. Knepley for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 24470034214SMatthew G. Knepley if (closure[c] == adj[q]) break; 24570034214SMatthew G. Knepley } 24670034214SMatthew G. Knepley if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 24770034214SMatthew G. Knepley } 24870034214SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr); 24970034214SMatthew G. Knepley } 25070034214SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, p, useClosure, &starSize, &star);CHKERRQ(ierr); 25170034214SMatthew G. Knepley *adjSize = numAdj; 25270034214SMatthew G. Knepley PetscFunctionReturn(0); 25370034214SMatthew G. Knepley } 25470034214SMatthew G. Knepley 25570034214SMatthew G. Knepley #undef __FUNCT__ 25670034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacency_Internal" 2575b317d89SToby Isaac PetscErrorCode DMPlexGetAdjacency_Internal(DM dm, PetscInt p, PetscBool useCone, PetscBool useTransitiveClosure, PetscBool useAnchors, PetscInt *adjSize, PetscInt *adj[]) 25870034214SMatthew G. Knepley { 25979bad331SMatthew G. Knepley static PetscInt asiz = 0; 2608b0b4c70SToby Isaac PetscInt maxAnchors = 1; 2618b0b4c70SToby Isaac PetscInt aStart = -1, aEnd = -1; 2628b0b4c70SToby Isaac PetscInt maxAdjSize; 2638b0b4c70SToby Isaac PetscSection aSec = NULL; 2648b0b4c70SToby Isaac IS aIS = NULL; 2658b0b4c70SToby Isaac const PetscInt *anchors; 26670034214SMatthew G. Knepley PetscErrorCode ierr; 26770034214SMatthew G. Knepley 26870034214SMatthew G. Knepley PetscFunctionBeginHot; 2695b317d89SToby Isaac if (useAnchors) { 270a17985deSToby Isaac ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 2718b0b4c70SToby Isaac if (aSec) { 2728b0b4c70SToby Isaac ierr = PetscSectionGetMaxDof(aSec,&maxAnchors);CHKERRQ(ierr); 27324c766afSToby Isaac maxAnchors = PetscMax(1,maxAnchors); 2748b0b4c70SToby Isaac ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 2758b0b4c70SToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 2768b0b4c70SToby Isaac } 2778b0b4c70SToby Isaac } 27879bad331SMatthew G. Knepley if (!*adj) { 27924c766afSToby Isaac PetscInt depth, coneSeries, supportSeries, maxC, maxS, pStart, pEnd; 28079bad331SMatthew G. Knepley 28124c766afSToby Isaac ierr = DMPlexGetChart(dm, &pStart,&pEnd);CHKERRQ(ierr); 28279bad331SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 28324c766afSToby Isaac ierr = DMPlexGetMaxSizes(dm, &maxC, &maxS);CHKERRQ(ierr); 28424c766afSToby Isaac coneSeries = (maxC > 1) ? ((PetscPowInt(maxC,depth+1)-1)/(maxC-1)) : depth+1; 28524c766afSToby Isaac supportSeries = (maxS > 1) ? ((PetscPowInt(maxS,depth+1)-1)/(maxS-1)) : depth+1; 28624c766afSToby Isaac asiz = PetscMax(PetscPowInt(maxS,depth)*coneSeries,PetscPowInt(maxC,depth)*supportSeries); 2878b0b4c70SToby Isaac asiz *= maxAnchors; 28824c766afSToby Isaac asiz = PetscMin(asiz,pEnd-pStart); 28979bad331SMatthew G. Knepley ierr = PetscMalloc1(asiz,adj);CHKERRQ(ierr); 29079bad331SMatthew G. Knepley } 29179bad331SMatthew G. Knepley if (*adjSize < 0) *adjSize = asiz; 2928b0b4c70SToby Isaac maxAdjSize = *adjSize; 29370034214SMatthew G. Knepley if (useTransitiveClosure) { 29479bad331SMatthew G. Knepley ierr = DMPlexGetAdjacency_Transitive_Internal(dm, p, useCone, adjSize, *adj);CHKERRQ(ierr); 29570034214SMatthew G. Knepley } else if (useCone) { 29679bad331SMatthew G. Knepley ierr = DMPlexGetAdjacency_Cone_Internal(dm, p, adjSize, *adj);CHKERRQ(ierr); 29770034214SMatthew G. Knepley } else { 29879bad331SMatthew G. Knepley ierr = DMPlexGetAdjacency_Support_Internal(dm, p, adjSize, *adj);CHKERRQ(ierr); 29970034214SMatthew G. Knepley } 3005b317d89SToby Isaac if (useAnchors && aSec) { 3018b0b4c70SToby Isaac PetscInt origSize = *adjSize; 3028b0b4c70SToby Isaac PetscInt numAdj = origSize; 3038b0b4c70SToby Isaac PetscInt i = 0, j; 3048b0b4c70SToby Isaac PetscInt *orig = *adj; 3058b0b4c70SToby Isaac 3068b0b4c70SToby Isaac while (i < origSize) { 3078b0b4c70SToby Isaac PetscInt p = orig[i]; 3088b0b4c70SToby Isaac PetscInt aDof = 0; 3098b0b4c70SToby Isaac 3108b0b4c70SToby Isaac if (p >= aStart && p < aEnd) { 3118b0b4c70SToby Isaac ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr); 3128b0b4c70SToby Isaac } 3138b0b4c70SToby Isaac if (aDof) { 3148b0b4c70SToby Isaac PetscInt aOff; 3158b0b4c70SToby Isaac PetscInt s, q; 3168b0b4c70SToby Isaac 3178b0b4c70SToby Isaac for (j = i + 1; j < numAdj; j++) { 3188b0b4c70SToby Isaac orig[j - 1] = orig[j]; 3198b0b4c70SToby Isaac } 3208b0b4c70SToby Isaac origSize--; 3218b0b4c70SToby Isaac numAdj--; 3228b0b4c70SToby Isaac ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 3238b0b4c70SToby Isaac for (s = 0; s < aDof; ++s) { 3248b0b4c70SToby Isaac for (q = 0; q < numAdj || (orig[numAdj++] = anchors[aOff+s],0); ++q) { 3258b0b4c70SToby Isaac if (anchors[aOff+s] == orig[q]) break; 3268b0b4c70SToby Isaac } 3278b0b4c70SToby Isaac if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 3288b0b4c70SToby Isaac } 3298b0b4c70SToby Isaac } 3308b0b4c70SToby Isaac else { 3318b0b4c70SToby Isaac i++; 3328b0b4c70SToby Isaac } 3338b0b4c70SToby Isaac } 3348b0b4c70SToby Isaac *adjSize = numAdj; 3358b0b4c70SToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 3368b0b4c70SToby Isaac } 33770034214SMatthew G. Knepley PetscFunctionReturn(0); 33870034214SMatthew G. Knepley } 33970034214SMatthew G. Knepley 34070034214SMatthew G. Knepley #undef __FUNCT__ 34170034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacency" 34270034214SMatthew G. Knepley /*@ 34370034214SMatthew G. Knepley DMPlexGetAdjacency - Return all points adjacent to the given point 34470034214SMatthew G. Knepley 34570034214SMatthew G. Knepley Input Parameters: 34670034214SMatthew G. Knepley + dm - The DM object 34770034214SMatthew G. Knepley . p - The point 34870034214SMatthew G. Knepley . adjSize - The maximum size of adj if it is non-NULL, or PETSC_DETERMINE 34970034214SMatthew G. Knepley - adj - Either NULL so that the array is allocated, or an existing array with size adjSize 35070034214SMatthew G. Knepley 35170034214SMatthew G. Knepley Output Parameters: 35270034214SMatthew G. Knepley + adjSize - The number of adjacent points 35370034214SMatthew G. Knepley - adj - The adjacent points 35470034214SMatthew G. Knepley 35570034214SMatthew G. Knepley Level: advanced 35670034214SMatthew G. Knepley 35770034214SMatthew G. Knepley Notes: The user must PetscFree the adj array if it was not passed in. 35870034214SMatthew G. Knepley 35970034214SMatthew G. Knepley .seealso: DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure(), DMPlexDistribute(), DMCreateMatrix(), DMPlexPreallocateOperator() 36070034214SMatthew G. Knepley @*/ 36170034214SMatthew G. Knepley PetscErrorCode DMPlexGetAdjacency(DM dm, PetscInt p, PetscInt *adjSize, PetscInt *adj[]) 36270034214SMatthew G. Knepley { 36370034214SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 36470034214SMatthew G. Knepley PetscErrorCode ierr; 36570034214SMatthew G. Knepley 36670034214SMatthew G. Knepley PetscFunctionBeginHot; 36770034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36870034214SMatthew G. Knepley PetscValidPointer(adjSize,3); 36970034214SMatthew G. Knepley PetscValidPointer(adj,4); 3705b317d89SToby Isaac ierr = DMPlexGetAdjacency_Internal(dm, p, mesh->useCone, mesh->useClosure, mesh->useAnchors, adjSize, adj);CHKERRQ(ierr); 37170034214SMatthew G. Knepley PetscFunctionReturn(0); 37270034214SMatthew G. Knepley } 373b0a623aaSMatthew G. Knepley #undef __FUNCT__ 374b0a623aaSMatthew G. Knepley #define __FUNCT__ "DMPlexCreateTwoSidedProcessSF" 375b0a623aaSMatthew G. Knepley /*@ 376b0a623aaSMatthew G. Knepley DMPlexCreateTwoSidedProcessSF - Create an SF which just has process connectivity 377b0a623aaSMatthew G. Knepley 378b0a623aaSMatthew G. Knepley Collective on DM 379b0a623aaSMatthew G. Knepley 380b0a623aaSMatthew G. Knepley Input Parameters: 381b0a623aaSMatthew G. Knepley + dm - The DM 382b0a623aaSMatthew G. Knepley - sfPoint - The PetscSF which encodes point connectivity 383b0a623aaSMatthew G. Knepley 384b0a623aaSMatthew G. Knepley Output Parameters: 385b0a623aaSMatthew G. Knepley + processRanks - A list of process neighbors, or NULL 386b0a623aaSMatthew G. Knepley - sfProcess - An SF encoding the two-sided process connectivity, or NULL 387b0a623aaSMatthew G. Knepley 388b0a623aaSMatthew G. Knepley Level: developer 389b0a623aaSMatthew G. Knepley 390b0a623aaSMatthew G. Knepley .seealso: PetscSFCreate(), DMPlexCreateProcessSF() 391b0a623aaSMatthew G. Knepley @*/ 392b0a623aaSMatthew G. Knepley PetscErrorCode DMPlexCreateTwoSidedProcessSF(DM dm, PetscSF sfPoint, PetscSection rootRankSection, IS rootRanks, PetscSection leafRankSection, IS leafRanks, IS *processRanks, PetscSF *sfProcess) 393b0a623aaSMatthew G. Knepley { 394b0a623aaSMatthew G. Knepley const PetscSFNode *remotePoints; 395b0a623aaSMatthew G. Knepley PetscInt *localPointsNew; 396b0a623aaSMatthew G. Knepley PetscSFNode *remotePointsNew; 397b0a623aaSMatthew G. Knepley const PetscInt *nranks; 398b0a623aaSMatthew G. Knepley PetscInt *ranksNew; 399b0a623aaSMatthew G. Knepley PetscBT neighbors; 400b0a623aaSMatthew G. Knepley PetscInt pStart, pEnd, p, numLeaves, l, numNeighbors, n; 401b0a623aaSMatthew G. Knepley PetscMPIInt numProcs, proc, rank; 402b0a623aaSMatthew G. Knepley PetscErrorCode ierr; 403b0a623aaSMatthew G. Knepley 404b0a623aaSMatthew G. Knepley PetscFunctionBegin; 405b0a623aaSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 406b0a623aaSMatthew G. Knepley PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2); 407b0a623aaSMatthew G. Knepley if (processRanks) {PetscValidPointer(processRanks, 3);} 408b0a623aaSMatthew G. Knepley if (sfProcess) {PetscValidPointer(sfProcess, 4);} 409b0a623aaSMatthew G. Knepley ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr); 410b0a623aaSMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 411b0a623aaSMatthew G. Knepley ierr = PetscSFGetGraph(sfPoint, NULL, &numLeaves, NULL, &remotePoints);CHKERRQ(ierr); 412b0a623aaSMatthew G. Knepley ierr = PetscBTCreate(numProcs, &neighbors);CHKERRQ(ierr); 413b0a623aaSMatthew G. Knepley ierr = PetscBTMemzero(numProcs, neighbors);CHKERRQ(ierr); 414b0a623aaSMatthew G. Knepley /* Compute root-to-leaf process connectivity */ 415b0a623aaSMatthew G. Knepley ierr = PetscSectionGetChart(rootRankSection, &pStart, &pEnd);CHKERRQ(ierr); 416b0a623aaSMatthew G. Knepley ierr = ISGetIndices(rootRanks, &nranks);CHKERRQ(ierr); 417b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 418b0a623aaSMatthew G. Knepley PetscInt ndof, noff, n; 419b0a623aaSMatthew G. Knepley 420b0a623aaSMatthew G. Knepley ierr = PetscSectionGetDof(rootRankSection, p, &ndof);CHKERRQ(ierr); 421b0a623aaSMatthew G. Knepley ierr = PetscSectionGetOffset(rootRankSection, p, &noff);CHKERRQ(ierr); 422b0a623aaSMatthew G. Knepley for (n = 0; n < ndof; ++n) {ierr = PetscBTSet(neighbors, nranks[noff+n]);} 423b0a623aaSMatthew G. Knepley } 424b0a623aaSMatthew G. Knepley ierr = ISRestoreIndices(rootRanks, &nranks);CHKERRQ(ierr); 425b0a623aaSMatthew G. Knepley /* Compute leaf-to-neighbor process connectivity */ 426b0a623aaSMatthew G. Knepley ierr = PetscSectionGetChart(leafRankSection, &pStart, &pEnd);CHKERRQ(ierr); 427b0a623aaSMatthew G. Knepley ierr = ISGetIndices(leafRanks, &nranks);CHKERRQ(ierr); 428b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 429b0a623aaSMatthew G. Knepley PetscInt ndof, noff, n; 430b0a623aaSMatthew G. Knepley 431b0a623aaSMatthew G. Knepley ierr = PetscSectionGetDof(leafRankSection, p, &ndof);CHKERRQ(ierr); 432b0a623aaSMatthew G. Knepley ierr = PetscSectionGetOffset(leafRankSection, p, &noff);CHKERRQ(ierr); 433b0a623aaSMatthew G. Knepley for (n = 0; n < ndof; ++n) {ierr = PetscBTSet(neighbors, nranks[noff+n]);} 434b0a623aaSMatthew G. Knepley } 435b0a623aaSMatthew G. Knepley ierr = ISRestoreIndices(leafRanks, &nranks);CHKERRQ(ierr); 436b0a623aaSMatthew G. Knepley /* Compute leaf-to-root process connectivity */ 437b0a623aaSMatthew G. Knepley for (l = 0; l < numLeaves; ++l) {PetscBTSet(neighbors, remotePoints[l].rank);} 438b0a623aaSMatthew G. Knepley /* Calculate edges */ 439b0a623aaSMatthew G. Knepley PetscBTClear(neighbors, rank); 440b0a623aaSMatthew G. Knepley for(proc = 0, numNeighbors = 0; proc < numProcs; ++proc) {if (PetscBTLookup(neighbors, proc)) ++numNeighbors;} 441b0a623aaSMatthew G. Knepley ierr = PetscMalloc1(numNeighbors, &ranksNew);CHKERRQ(ierr); 442b0a623aaSMatthew G. Knepley ierr = PetscMalloc1(numNeighbors, &localPointsNew);CHKERRQ(ierr); 443b0a623aaSMatthew G. Knepley ierr = PetscMalloc1(numNeighbors, &remotePointsNew);CHKERRQ(ierr); 444b0a623aaSMatthew G. Knepley for(proc = 0, n = 0; proc < numProcs; ++proc) { 445b0a623aaSMatthew G. Knepley if (PetscBTLookup(neighbors, proc)) { 446b0a623aaSMatthew G. Knepley ranksNew[n] = proc; 447b0a623aaSMatthew G. Knepley localPointsNew[n] = proc; 448b0a623aaSMatthew G. Knepley remotePointsNew[n].index = rank; 449b0a623aaSMatthew G. Knepley remotePointsNew[n].rank = proc; 450b0a623aaSMatthew G. Knepley ++n; 451b0a623aaSMatthew G. Knepley } 452b0a623aaSMatthew G. Knepley } 453b0a623aaSMatthew G. Knepley ierr = PetscBTDestroy(&neighbors);CHKERRQ(ierr); 454b0a623aaSMatthew G. Knepley if (processRanks) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numNeighbors, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);} 455b0a623aaSMatthew G. Knepley else {ierr = PetscFree(ranksNew);CHKERRQ(ierr);} 456b0a623aaSMatthew G. Knepley if (sfProcess) { 457b0a623aaSMatthew G. Knepley ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 458b0a623aaSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) *sfProcess, "Two-Sided Process SF");CHKERRQ(ierr); 459b0a623aaSMatthew G. Knepley ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 460b0a623aaSMatthew G. Knepley ierr = PetscSFSetGraph(*sfProcess, numProcs, numNeighbors, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 461b0a623aaSMatthew G. Knepley } 462b0a623aaSMatthew G. Knepley PetscFunctionReturn(0); 463b0a623aaSMatthew G. Knepley } 464b0a623aaSMatthew G. Knepley 465b0a623aaSMatthew G. Knepley #undef __FUNCT__ 466b0a623aaSMatthew G. Knepley #define __FUNCT__ "DMPlexDistributeOwnership" 467b0a623aaSMatthew G. Knepley /*@ 468b0a623aaSMatthew G. Knepley DMPlexDistributeOwnership - Compute owner information for shared points. This basically gets two-sided for an SF. 469b0a623aaSMatthew G. Knepley 470b0a623aaSMatthew G. Knepley Collective on DM 471b0a623aaSMatthew G. Knepley 472b0a623aaSMatthew G. Knepley Input Parameter: 473b0a623aaSMatthew G. Knepley . dm - The DM 474b0a623aaSMatthew G. Knepley 475b0a623aaSMatthew G. Knepley Output Parameters: 476b0a623aaSMatthew G. Knepley + rootSection - The number of leaves for a given root point 477b0a623aaSMatthew G. Knepley . rootrank - The rank of each edge into the root point 478b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point 479b0a623aaSMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point 480b0a623aaSMatthew G. Knepley 481b0a623aaSMatthew G. Knepley Level: developer 482b0a623aaSMatthew G. Knepley 483b0a623aaSMatthew G. Knepley .seealso: DMPlexCreateOverlap() 484b0a623aaSMatthew G. Knepley @*/ 485b0a623aaSMatthew G. Knepley PetscErrorCode DMPlexDistributeOwnership(DM dm, PetscSection rootSection, IS *rootrank, PetscSection leafSection, IS *leafrank) 486b0a623aaSMatthew G. Knepley { 487b0a623aaSMatthew G. Knepley MPI_Comm comm; 488b0a623aaSMatthew G. Knepley PetscSF sfPoint; 489b0a623aaSMatthew G. Knepley const PetscInt *rootdegree; 490b0a623aaSMatthew G. Knepley PetscInt *myrank, *remoterank; 491b0a623aaSMatthew G. Knepley PetscInt pStart, pEnd, p, nedges; 492b0a623aaSMatthew G. Knepley PetscMPIInt rank; 493b0a623aaSMatthew G. Knepley PetscErrorCode ierr; 494b0a623aaSMatthew G. Knepley 495b0a623aaSMatthew G. Knepley PetscFunctionBegin; 496b0a623aaSMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 497b0a623aaSMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 498b0a623aaSMatthew G. Knepley ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 499b0a623aaSMatthew G. Knepley ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 500b0a623aaSMatthew G. Knepley /* Compute number of leaves for each root */ 501b0a623aaSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) rootSection, "Root Section");CHKERRQ(ierr); 502b0a623aaSMatthew G. Knepley ierr = PetscSectionSetChart(rootSection, pStart, pEnd);CHKERRQ(ierr); 503b0a623aaSMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(sfPoint, &rootdegree);CHKERRQ(ierr); 504b0a623aaSMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(sfPoint, &rootdegree);CHKERRQ(ierr); 505b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) {ierr = PetscSectionSetDof(rootSection, p, rootdegree[p-pStart]);CHKERRQ(ierr);} 506b0a623aaSMatthew G. Knepley ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 507b0a623aaSMatthew G. Knepley /* Gather rank of each leaf to root */ 508b0a623aaSMatthew G. Knepley ierr = PetscSectionGetStorageSize(rootSection, &nedges);CHKERRQ(ierr); 509b0a623aaSMatthew G. Knepley ierr = PetscMalloc1(pEnd-pStart, &myrank);CHKERRQ(ierr); 510b0a623aaSMatthew G. Knepley ierr = PetscMalloc1(nedges, &remoterank);CHKERRQ(ierr); 511b0a623aaSMatthew G. Knepley for (p = 0; p < pEnd-pStart; ++p) myrank[p] = rank; 512b0a623aaSMatthew G. Knepley ierr = PetscSFGatherBegin(sfPoint, MPIU_INT, myrank, remoterank);CHKERRQ(ierr); 513b0a623aaSMatthew G. Knepley ierr = PetscSFGatherEnd(sfPoint, MPIU_INT, myrank, remoterank);CHKERRQ(ierr); 514b0a623aaSMatthew G. Knepley ierr = PetscFree(myrank);CHKERRQ(ierr); 515b0a623aaSMatthew G. Knepley ierr = ISCreateGeneral(comm, nedges, remoterank, PETSC_OWN_POINTER, rootrank);CHKERRQ(ierr); 516b0a623aaSMatthew G. Knepley /* Distribute remote ranks to leaves */ 517b0a623aaSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) leafSection, "Leaf Section");CHKERRQ(ierr); 518b0a623aaSMatthew G. Knepley ierr = DMPlexDistributeFieldIS(dm, sfPoint, rootSection, *rootrank, leafSection, leafrank);CHKERRQ(ierr); 519b0a623aaSMatthew G. Knepley PetscFunctionReturn(0); 520b0a623aaSMatthew G. Knepley } 521b0a623aaSMatthew G. Knepley 522b0a623aaSMatthew G. Knepley #undef __FUNCT__ 523b0a623aaSMatthew G. Knepley #define __FUNCT__ "DMPlexCreateOverlap" 524278397a0SMatthew G. Knepley /*@C 525b0a623aaSMatthew G. Knepley DMPlexCreateOverlap - Compute owner information for shared points. This basically gets two-sided for an SF. 526b0a623aaSMatthew G. Knepley 527b0a623aaSMatthew G. Knepley Collective on DM 528b0a623aaSMatthew G. Knepley 529b0a623aaSMatthew G. Knepley Input Parameters: 530b0a623aaSMatthew G. Knepley + dm - The DM 531b0a623aaSMatthew G. Knepley . rootSection - The number of leaves for a given root point 532b0a623aaSMatthew G. Knepley . rootrank - The rank of each edge into the root point 533b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point 534b0a623aaSMatthew G. Knepley - leafrank - The rank of each process sharing a leaf point 535b0a623aaSMatthew G. Knepley 536b0a623aaSMatthew G. Knepley Output Parameters: 537b0a623aaSMatthew G. Knepley + ovRootSection - The number of new overlap points for each neighboring process 538b0a623aaSMatthew G. Knepley . ovRootPoints - The new overlap points for each neighboring process 539b0a623aaSMatthew G. Knepley . ovLeafSection - The number of new overlap points from each neighboring process 540b0a623aaSMatthew G. Knepley - ovLeafPoints - The new overlap points from each neighboring process 541b0a623aaSMatthew G. Knepley 542b0a623aaSMatthew G. Knepley Level: developer 543b0a623aaSMatthew G. Knepley 544b0a623aaSMatthew G. Knepley .seealso: DMPlexDistributeOwnership() 545b0a623aaSMatthew G. Knepley @*/ 546*e540f424SMichael Lange PetscErrorCode DMPlexCreateOverlap(DM dm, PetscSection rootSection, IS rootrank, PetscSection leafSection, IS leafrank, PetscSF *overlapSF) 547b0a623aaSMatthew G. Knepley { 548*e540f424SMichael Lange MPI_Comm comm; 549b0a623aaSMatthew G. Knepley DMLabel ovAdjByRank; /* A DMLabel containing all points adjacent to shared points, separated by rank (value in label) */ 550b0a623aaSMatthew G. Knepley PetscSF sfPoint, sfProc; 551b0a623aaSMatthew G. Knepley IS valueIS; 552*e540f424SMichael Lange DMLabel ovLeafLabel; 553b0a623aaSMatthew G. Knepley const PetscSFNode *remote; 554b0a623aaSMatthew G. Knepley const PetscInt *local; 555b0a623aaSMatthew G. Knepley const PetscInt *nrank, *rrank, *neighbors; 556*e540f424SMichael Lange PetscSFNode *ovRootPoints, *ovLeafPoints, *remotePoints; 557*e540f424SMichael Lange PetscSection ovRootSection, ovLeafSection; 558b0a623aaSMatthew G. Knepley PetscInt *adj = NULL; 559b0a623aaSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, nleaves, l, numNeighbors, n, ovSize; 560*e540f424SMichael Lange PetscInt idx, numRemote; 561b0a623aaSMatthew G. Knepley PetscMPIInt rank, numProcs; 562*e540f424SMichael Lange PetscBool flg; 563b0a623aaSMatthew G. Knepley PetscErrorCode ierr; 564b0a623aaSMatthew G. Knepley 565b0a623aaSMatthew G. Knepley PetscFunctionBegin; 566*e540f424SMichael Lange ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 567*e540f424SMichael Lange ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 568*e540f424SMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 569b0a623aaSMatthew G. Knepley ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 570b0a623aaSMatthew G. Knepley ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 571b0a623aaSMatthew G. Knepley ierr = PetscSectionGetChart(leafSection, &sStart, &sEnd);CHKERRQ(ierr); 572b0a623aaSMatthew G. Knepley ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr); 573b0a623aaSMatthew G. Knepley ierr = DMLabelCreate("Overlap adjacency", &ovAdjByRank);CHKERRQ(ierr); 574b0a623aaSMatthew G. Knepley /* Handle leaves: shared with the root point */ 575b0a623aaSMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 576b0a623aaSMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, a; 577b0a623aaSMatthew G. Knepley 578b0a623aaSMatthew G. Knepley ierr = DMPlexGetAdjacency(dm, local[l], &adjSize, &adj);CHKERRQ(ierr); 579b0a623aaSMatthew G. Knepley for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(ovAdjByRank, adj[a], remote[l].rank);CHKERRQ(ierr);} 580b0a623aaSMatthew G. Knepley } 581b0a623aaSMatthew G. Knepley ierr = ISGetIndices(rootrank, &rrank);CHKERRQ(ierr); 582b0a623aaSMatthew G. Knepley ierr = ISGetIndices(leafrank, &nrank);CHKERRQ(ierr); 583b0a623aaSMatthew G. Knepley /* Handle roots */ 584b0a623aaSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 585b0a623aaSMatthew G. Knepley PetscInt adjSize = PETSC_DETERMINE, neighbors = 0, noff, n, a; 586b0a623aaSMatthew G. Knepley 587b0a623aaSMatthew G. Knepley if ((p >= sStart) && (p < sEnd)) { 588b0a623aaSMatthew G. Knepley /* Some leaves share a root with other leaves on different processes */ 589b0a623aaSMatthew G. Knepley ierr = PetscSectionGetDof(leafSection, p, &neighbors);CHKERRQ(ierr); 590b0a623aaSMatthew G. Knepley if (neighbors) { 591b0a623aaSMatthew G. Knepley ierr = PetscSectionGetOffset(leafSection, p, &noff);CHKERRQ(ierr); 592b0a623aaSMatthew G. Knepley ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr); 593b0a623aaSMatthew G. Knepley for (n = 0; n < neighbors; ++n) { 594b0a623aaSMatthew G. Knepley const PetscInt remoteRank = nrank[noff+n]; 595b0a623aaSMatthew G. Knepley 596b0a623aaSMatthew G. Knepley if (remoteRank == rank) continue; 597b0a623aaSMatthew G. Knepley for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(ovAdjByRank, adj[a], remoteRank);CHKERRQ(ierr);} 598b0a623aaSMatthew G. Knepley } 599b0a623aaSMatthew G. Knepley } 600b0a623aaSMatthew G. Knepley } 601b0a623aaSMatthew G. Knepley /* Roots are shared with leaves */ 602b0a623aaSMatthew G. Knepley ierr = PetscSectionGetDof(rootSection, p, &neighbors);CHKERRQ(ierr); 603b0a623aaSMatthew G. Knepley if (!neighbors) continue; 604b0a623aaSMatthew G. Knepley ierr = PetscSectionGetOffset(rootSection, p, &noff);CHKERRQ(ierr); 605b0a623aaSMatthew G. Knepley ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr); 606b0a623aaSMatthew G. Knepley for (n = 0; n < neighbors; ++n) { 607b0a623aaSMatthew G. Knepley const PetscInt remoteRank = rrank[noff+n]; 608b0a623aaSMatthew G. Knepley 609b0a623aaSMatthew G. Knepley if (remoteRank == rank) continue; 610b0a623aaSMatthew G. Knepley for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(ovAdjByRank, adj[a], remoteRank);CHKERRQ(ierr);} 611b0a623aaSMatthew G. Knepley } 612b0a623aaSMatthew G. Knepley } 613b0a623aaSMatthew G. Knepley ierr = PetscFree(adj);CHKERRQ(ierr); 614b0a623aaSMatthew G. Knepley ierr = ISRestoreIndices(rootrank, &rrank);CHKERRQ(ierr); 615b0a623aaSMatthew G. Knepley ierr = ISRestoreIndices(leafrank, &nrank);CHKERRQ(ierr); 616*e540f424SMichael Lange ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-overlap_view", &flg);CHKERRQ(ierr); 617*e540f424SMichael Lange if (flg) { 618b0a623aaSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 619b0a623aaSMatthew G. Knepley ierr = DMLabelView(ovAdjByRank, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 620b0a623aaSMatthew G. Knepley } 621b0a623aaSMatthew G. Knepley /* Convert to (point, rank) and use actual owners */ 622*e540f424SMichael Lange ierr = PetscSectionCreate(comm, &ovRootSection);CHKERRQ(ierr); 623*e540f424SMichael Lange ierr = PetscObjectSetName((PetscObject) ovRootSection, "Overlap Root Section");CHKERRQ(ierr); 624b0a623aaSMatthew G. Knepley ierr = PetscSectionSetChart(ovRootSection, 0, numProcs);CHKERRQ(ierr); 625b0a623aaSMatthew G. Knepley ierr = DMLabelGetValueIS(ovAdjByRank, &valueIS);CHKERRQ(ierr); 626b0a623aaSMatthew G. Knepley ierr = ISGetLocalSize(valueIS, &numNeighbors);CHKERRQ(ierr); 627b0a623aaSMatthew G. Knepley ierr = ISGetIndices(valueIS, &neighbors);CHKERRQ(ierr); 628b0a623aaSMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 629b0a623aaSMatthew G. Knepley PetscInt numPoints; 630b0a623aaSMatthew G. Knepley 631b0a623aaSMatthew G. Knepley ierr = DMLabelGetStratumSize(ovAdjByRank, neighbors[n], &numPoints);CHKERRQ(ierr); 632b0a623aaSMatthew G. Knepley ierr = PetscSectionAddDof(ovRootSection, neighbors[n], numPoints);CHKERRQ(ierr); 633b0a623aaSMatthew G. Knepley } 634b0a623aaSMatthew G. Knepley ierr = PetscSectionSetUp(ovRootSection);CHKERRQ(ierr); 635b0a623aaSMatthew G. Knepley ierr = PetscSectionGetStorageSize(ovRootSection, &ovSize);CHKERRQ(ierr); 636*e540f424SMichael Lange ierr = PetscMalloc1(ovSize, &ovRootPoints);CHKERRQ(ierr); 637b0a623aaSMatthew G. Knepley ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr); 638b0a623aaSMatthew G. Knepley for (n = 0; n < numNeighbors; ++n) { 639b0a623aaSMatthew G. Knepley IS pointIS; 640b0a623aaSMatthew G. Knepley const PetscInt *points; 641b0a623aaSMatthew G. Knepley PetscInt off, numPoints, p; 642b0a623aaSMatthew G. Knepley 643b0a623aaSMatthew G. Knepley ierr = PetscSectionGetOffset(ovRootSection, neighbors[n], &off);CHKERRQ(ierr); 644b0a623aaSMatthew G. Knepley ierr = DMLabelGetStratumIS(ovAdjByRank, neighbors[n], &pointIS);CHKERRQ(ierr); 645b0a623aaSMatthew G. Knepley ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 646b0a623aaSMatthew G. Knepley ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 647b0a623aaSMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 648b0a623aaSMatthew G. Knepley ierr = PetscFindInt(points[p], nleaves, local, &l);CHKERRQ(ierr); 649*e540f424SMichael Lange if (l >= 0) {ovRootPoints[off+p] = remote[l];} 650*e540f424SMichael Lange else {ovRootPoints[off+p].index = points[p]; ovRootPoints[off+p].rank = rank;} 651b0a623aaSMatthew G. Knepley } 652b0a623aaSMatthew G. Knepley ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 653b0a623aaSMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 654b0a623aaSMatthew G. Knepley } 655b0a623aaSMatthew G. Knepley ierr = ISRestoreIndices(valueIS, &neighbors);CHKERRQ(ierr); 656b0a623aaSMatthew G. Knepley ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 657b0a623aaSMatthew G. Knepley ierr = DMLabelDestroy(&ovAdjByRank);CHKERRQ(ierr); 658b0a623aaSMatthew G. Knepley /* Make process SF */ 659b0a623aaSMatthew G. Knepley ierr = DMPlexCreateTwoSidedProcessSF(dm, sfPoint, rootSection, rootrank, leafSection, leafrank, NULL, &sfProc);CHKERRQ(ierr); 660*e540f424SMichael Lange if (flg) { 661b0a623aaSMatthew G. Knepley ierr = PetscSFView(sfProc, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 662b0a623aaSMatthew G. Knepley } 663b0a623aaSMatthew G. Knepley /* Communicate overlap */ 664*e540f424SMichael Lange ierr = PetscSectionCreate(comm, &ovLeafSection);CHKERRQ(ierr); 665*e540f424SMichael Lange ierr = PetscObjectSetName((PetscObject) ovLeafSection, "Overlap Leaf Section");CHKERRQ(ierr); 666*e540f424SMichael Lange ierr = DMPlexDistributeData(dm, sfProc, ovRootSection, MPIU_2INT, ovRootPoints, ovLeafSection, (void**) &ovLeafPoints);CHKERRQ(ierr); 667*e540f424SMichael Lange /* Filter remote contributions (ovLeafPoints) into the overlapSF */ 668*e540f424SMichael Lange ierr = DMLabelCreate("ovLeafs", &ovLeafLabel);CHKERRQ(ierr); 669*e540f424SMichael Lange ierr = PetscSectionGetStorageSize(ovLeafSection, &ovSize);CHKERRQ(ierr); 670*e540f424SMichael Lange for (p = 0; p < ovSize; p++) { 671*e540f424SMichael Lange /* Don't import points from yourself */ 672*e540f424SMichael Lange if (ovLeafPoints[p].rank == rank) continue; 673*e540f424SMichael Lange ierr = DMLabelSetValue(ovLeafLabel, ovLeafPoints[p].index, ovLeafPoints[p].rank);CHKERRQ(ierr); 674*e540f424SMichael Lange } 675*e540f424SMichael Lange /* Don't import points already in the pointSF */ 676*e540f424SMichael Lange for (l = 0; l < nleaves; ++l) { 677*e540f424SMichael Lange ierr = DMLabelClearValue(ovLeafLabel, remote[l].index, remote[l].rank);CHKERRQ(ierr); 678*e540f424SMichael Lange } 679*e540f424SMichael Lange for (numRemote = 0, n = 0; n < numProcs; ++n) { 680*e540f424SMichael Lange PetscInt numPoints; 681*e540f424SMichael Lange ierr = DMLabelGetStratumSize(ovLeafLabel, n, &numPoints);CHKERRQ(ierr); 682*e540f424SMichael Lange numRemote += numPoints; 683*e540f424SMichael Lange } 684*e540f424SMichael Lange ierr = PetscMalloc1(numRemote, &remotePoints);CHKERRQ(ierr); 685*e540f424SMichael Lange for (idx = 0, n = 0; n < numProcs; ++n) { 686*e540f424SMichael Lange IS remoteRootIS; 687*e540f424SMichael Lange PetscInt numPoints; 688*e540f424SMichael Lange const PetscInt *remoteRoots; 689*e540f424SMichael Lange ierr = DMLabelGetStratumSize(ovLeafLabel, n, &numPoints);CHKERRQ(ierr); 690*e540f424SMichael Lange if (numPoints <= 0) continue; 691*e540f424SMichael Lange ierr = DMLabelGetStratumIS(ovLeafLabel, n, &remoteRootIS);CHKERRQ(ierr); 692*e540f424SMichael Lange ierr = ISGetIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 693*e540f424SMichael Lange for (p = 0; p < numPoints; p++) { 694*e540f424SMichael Lange remotePoints[idx].index = remoteRoots[p]; 695*e540f424SMichael Lange remotePoints[idx].rank = n; 696*e540f424SMichael Lange idx++; 697*e540f424SMichael Lange } 698*e540f424SMichael Lange ierr = ISRestoreIndices(remoteRootIS, &remoteRoots);CHKERRQ(ierr); 699*e540f424SMichael Lange } 700*e540f424SMichael Lange ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), overlapSF);CHKERRQ(ierr); 701*e540f424SMichael Lange ierr = PetscObjectSetName((PetscObject) *overlapSF, "Overlap SF");CHKERRQ(ierr); 702*e540f424SMichael Lange ierr = PetscSFSetFromOptions(*overlapSF);CHKERRQ(ierr); 703*e540f424SMichael Lange ierr = PetscSFSetGraph(*overlapSF, pEnd-pStart, numRemote, NULL, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 704*e540f424SMichael Lange if (flg) { 705*e540f424SMichael Lange ierr = PetscPrintf(comm, "Overlap SF\n");CHKERRQ(ierr); 706*e540f424SMichael Lange ierr = PetscSFView(*overlapSF, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 707*e540f424SMichael Lange } 708*e540f424SMichael Lange /* Clean up */ 709b0a623aaSMatthew G. Knepley ierr = PetscSFDestroy(&sfProc);CHKERRQ(ierr); 710*e540f424SMichael Lange ierr = PetscFree(ovRootPoints);CHKERRQ(ierr); 711*e540f424SMichael Lange ierr = PetscSectionDestroy(&ovRootSection);CHKERRQ(ierr); 712*e540f424SMichael Lange ierr = PetscFree(ovLeafPoints);CHKERRQ(ierr); 713*e540f424SMichael Lange ierr = PetscSectionDestroy(&ovLeafSection);CHKERRQ(ierr); 714b0a623aaSMatthew G. Knepley PetscFunctionReturn(0); 715b0a623aaSMatthew G. Knepley } 71670034214SMatthew G. Knepley 71770034214SMatthew G. Knepley #undef __FUNCT__ 71870034214SMatthew G. Knepley #define __FUNCT__ "DMPlexDistributeField" 71970034214SMatthew G. Knepley /*@ 72070034214SMatthew G. Knepley DMPlexDistributeField - Distribute field data to match a given PetscSF, usually the SF from mesh distribution 72170034214SMatthew G. Knepley 72270034214SMatthew G. Knepley Collective on DM 72370034214SMatthew G. Knepley 72470034214SMatthew G. Knepley Input Parameters: 72570034214SMatthew G. Knepley + dm - The DMPlex object 72670034214SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern 72770034214SMatthew G. Knepley . originalSection - The PetscSection for existing data layout 72870034214SMatthew G. Knepley - originalVec - The existing data 72970034214SMatthew G. Knepley 73070034214SMatthew G. Knepley Output Parameters: 73170034214SMatthew G. Knepley + newSection - The PetscSF describing the new data layout 73270034214SMatthew G. Knepley - newVec - The new data 73370034214SMatthew G. Knepley 73470034214SMatthew G. Knepley Level: developer 73570034214SMatthew G. Knepley 7361e8fc25dSMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeFieldIS(), DMPlexDistributeData() 73770034214SMatthew G. Knepley @*/ 73870034214SMatthew G. Knepley PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 73970034214SMatthew G. Knepley { 74070034214SMatthew G. Knepley PetscSF fieldSF; 74170034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize; 74270034214SMatthew G. Knepley PetscScalar *originalValues, *newValues; 74370034214SMatthew G. Knepley PetscErrorCode ierr; 74470034214SMatthew G. Knepley 74570034214SMatthew G. Knepley PetscFunctionBegin; 74670034214SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_DistributeField,dm,0,0,0);CHKERRQ(ierr); 74770034214SMatthew G. Knepley ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 74870034214SMatthew G. Knepley 74970034214SMatthew G. Knepley ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 75070034214SMatthew G. Knepley ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 75170034214SMatthew G. Knepley ierr = VecSetType(newVec,dm->vectype);CHKERRQ(ierr); 75270034214SMatthew G. Knepley 75370034214SMatthew G. Knepley ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 75470034214SMatthew G. Knepley ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 75570034214SMatthew G. Knepley ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 75670034214SMatthew G. Knepley ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 75770034214SMatthew G. Knepley ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 75870034214SMatthew G. Knepley ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 75970034214SMatthew G. Knepley ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 76070034214SMatthew G. Knepley ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 76170034214SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_DistributeField,dm,0,0,0);CHKERRQ(ierr); 76270034214SMatthew G. Knepley PetscFunctionReturn(0); 76370034214SMatthew G. Knepley } 76470034214SMatthew G. Knepley 76570034214SMatthew G. Knepley #undef __FUNCT__ 7661e8fc25dSMatthew G. Knepley #define __FUNCT__ "DMPlexDistributeFieldIS" 7671e8fc25dSMatthew G. Knepley /*@ 7681e8fc25dSMatthew G. Knepley DMPlexDistributeFieldIS - Distribute field data to match a given PetscSF, usually the SF from mesh distribution 7691e8fc25dSMatthew G. Knepley 7701e8fc25dSMatthew G. Knepley Collective on DM 7711e8fc25dSMatthew G. Knepley 7721e8fc25dSMatthew G. Knepley Input Parameters: 7731e8fc25dSMatthew G. Knepley + dm - The DMPlex object 7741e8fc25dSMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern 7751e8fc25dSMatthew G. Knepley . originalSection - The PetscSection for existing data layout 7761e8fc25dSMatthew G. Knepley - originalIS - The existing data 7771e8fc25dSMatthew G. Knepley 7781e8fc25dSMatthew G. Knepley Output Parameters: 7791e8fc25dSMatthew G. Knepley + newSection - The PetscSF describing the new data layout 7801e8fc25dSMatthew G. Knepley - newIS - The new data 7811e8fc25dSMatthew G. Knepley 7821e8fc25dSMatthew G. Knepley Level: developer 7831e8fc25dSMatthew G. Knepley 7841e8fc25dSMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexDistributeData() 7851e8fc25dSMatthew G. Knepley @*/ 7861e8fc25dSMatthew G. Knepley PetscErrorCode DMPlexDistributeFieldIS(DM dm, PetscSF pointSF, PetscSection originalSection, IS originalIS, PetscSection newSection, IS *newIS) 7871e8fc25dSMatthew G. Knepley { 7881e8fc25dSMatthew G. Knepley PetscSF fieldSF; 7891e8fc25dSMatthew G. Knepley PetscInt *newValues, *remoteOffsets, fieldSize; 7901e8fc25dSMatthew G. Knepley const PetscInt *originalValues; 7911e8fc25dSMatthew G. Knepley PetscErrorCode ierr; 7921e8fc25dSMatthew G. Knepley 7931e8fc25dSMatthew G. Knepley PetscFunctionBegin; 7941e8fc25dSMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_DistributeField,dm,0,0,0);CHKERRQ(ierr); 7951e8fc25dSMatthew G. Knepley ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 7961e8fc25dSMatthew G. Knepley 7971e8fc25dSMatthew G. Knepley ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 7981e8fc25dSMatthew G. Knepley ierr = PetscMalloc(fieldSize * sizeof(PetscInt), &newValues);CHKERRQ(ierr); 7991e8fc25dSMatthew G. Knepley 8001e8fc25dSMatthew G. Knepley ierr = ISGetIndices(originalIS, &originalValues);CHKERRQ(ierr); 8011e8fc25dSMatthew G. Knepley ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 8021e8fc25dSMatthew G. Knepley ierr = PetscSFBcastBegin(fieldSF, MPIU_INT, originalValues, newValues);CHKERRQ(ierr); 8031e8fc25dSMatthew G. Knepley ierr = PetscSFBcastEnd(fieldSF, MPIU_INT, originalValues, newValues);CHKERRQ(ierr); 8041e8fc25dSMatthew G. Knepley ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 8051e8fc25dSMatthew G. Knepley ierr = ISRestoreIndices(originalIS, &originalValues);CHKERRQ(ierr); 8061e8fc25dSMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject) pointSF), fieldSize, newValues, PETSC_OWN_POINTER, newIS);CHKERRQ(ierr); 8071e8fc25dSMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_DistributeField,dm,0,0,0);CHKERRQ(ierr); 8081e8fc25dSMatthew G. Knepley PetscFunctionReturn(0); 8091e8fc25dSMatthew G. Knepley } 8101e8fc25dSMatthew G. Knepley 8111e8fc25dSMatthew G. Knepley #undef __FUNCT__ 81270034214SMatthew G. Knepley #define __FUNCT__ "DMPlexDistributeData" 81370034214SMatthew G. Knepley /*@ 81470034214SMatthew G. Knepley DMPlexDistributeData - Distribute field data to match a given PetscSF, usually the SF from mesh distribution 81570034214SMatthew G. Knepley 81670034214SMatthew G. Knepley Collective on DM 81770034214SMatthew G. Knepley 81870034214SMatthew G. Knepley Input Parameters: 81970034214SMatthew G. Knepley + dm - The DMPlex object 82070034214SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern 82170034214SMatthew G. Knepley . originalSection - The PetscSection for existing data layout 82270034214SMatthew G. Knepley . datatype - The type of data 82370034214SMatthew G. Knepley - originalData - The existing data 82470034214SMatthew G. Knepley 82570034214SMatthew G. Knepley Output Parameters: 8261e8fc25dSMatthew G. Knepley + newSection - The PetscSection describing the new data layout 82770034214SMatthew G. Knepley - newData - The new data 82870034214SMatthew G. Knepley 82970034214SMatthew G. Knepley Level: developer 83070034214SMatthew G. Knepley 83170034214SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField() 83270034214SMatthew G. Knepley @*/ 83370034214SMatthew G. Knepley PetscErrorCode DMPlexDistributeData(DM dm, PetscSF pointSF, PetscSection originalSection, MPI_Datatype datatype, void *originalData, PetscSection newSection, void **newData) 83470034214SMatthew G. Knepley { 83570034214SMatthew G. Knepley PetscSF fieldSF; 83670034214SMatthew G. Knepley PetscInt *remoteOffsets, fieldSize; 83770034214SMatthew G. Knepley PetscMPIInt dataSize; 83870034214SMatthew G. Knepley PetscErrorCode ierr; 83970034214SMatthew G. Knepley 84070034214SMatthew G. Knepley PetscFunctionBegin; 84170034214SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_DistributeData,dm,0,0,0);CHKERRQ(ierr); 84270034214SMatthew G. Knepley ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 84370034214SMatthew G. Knepley 84470034214SMatthew G. Knepley ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 84570034214SMatthew G. Knepley ierr = MPI_Type_size(datatype, &dataSize);CHKERRQ(ierr); 84670034214SMatthew G. Knepley ierr = PetscMalloc(fieldSize * dataSize, newData);CHKERRQ(ierr); 84770034214SMatthew G. Knepley 84870034214SMatthew G. Knepley ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 84970034214SMatthew G. Knepley ierr = PetscSFBcastBegin(fieldSF, datatype, originalData, *newData);CHKERRQ(ierr); 85070034214SMatthew G. Knepley ierr = PetscSFBcastEnd(fieldSF, datatype, originalData, *newData);CHKERRQ(ierr); 85170034214SMatthew G. Knepley ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 85270034214SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_DistributeData,dm,0,0,0);CHKERRQ(ierr); 85370034214SMatthew G. Knepley PetscFunctionReturn(0); 85470034214SMatthew G. Knepley } 85570034214SMatthew G. Knepley 85670034214SMatthew G. Knepley #undef __FUNCT__ 857cc71bff1SMichael Lange #define __FUNCT__ "DMPlexDistributeCones" 858cc71bff1SMichael Lange PetscErrorCode DMPlexDistributeCones(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping renumbering, DM dmParallel) 859cc71bff1SMichael Lange { 860cc71bff1SMichael Lange DM_Plex *pmesh = (DM_Plex*) (dmParallel)->data; 861cc71bff1SMichael Lange MPI_Comm comm; 862cc71bff1SMichael Lange PetscSF coneSF; 863cc71bff1SMichael Lange PetscSection originalConeSection, newConeSection; 864cc71bff1SMichael Lange PetscInt *remoteOffsets, *cones, *newCones, newConesSize; 865cc71bff1SMichael Lange PetscBool flg; 866cc71bff1SMichael Lange PetscErrorCode ierr; 867cc71bff1SMichael Lange 868cc71bff1SMichael Lange PetscFunctionBegin; 869cc71bff1SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 870cc71bff1SMichael Lange PetscValidPointer(dmParallel,4); 871cc71bff1SMichael Lange ierr = PetscLogEventBegin(DMPLEX_DistributeCones,dm,0,0,0);CHKERRQ(ierr); 872cc71bff1SMichael Lange 873cc71bff1SMichael Lange /* Distribute cone section */ 874cc71bff1SMichael Lange ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 875cc71bff1SMichael Lange ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 876cc71bff1SMichael Lange ierr = DMPlexGetConeSection(dmParallel, &newConeSection);CHKERRQ(ierr); 877cc71bff1SMichael Lange ierr = PetscSFDistributeSection(migrationSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 878cc71bff1SMichael Lange ierr = DMSetUp(dmParallel);CHKERRQ(ierr); 879cc71bff1SMichael Lange { 880cc71bff1SMichael Lange PetscInt pStart, pEnd, p; 881cc71bff1SMichael Lange 882cc71bff1SMichael Lange ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 883cc71bff1SMichael Lange for (p = pStart; p < pEnd; ++p) { 884cc71bff1SMichael Lange PetscInt coneSize; 885cc71bff1SMichael Lange ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 886cc71bff1SMichael Lange pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 887cc71bff1SMichael Lange } 888cc71bff1SMichael Lange } 889cc71bff1SMichael Lange /* Communicate and renumber cones */ 890cc71bff1SMichael Lange ierr = PetscSFCreateSectionSF(migrationSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 891cc71bff1SMichael Lange ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 892cc71bff1SMichael Lange ierr = DMPlexGetCones(dmParallel, &newCones);CHKERRQ(ierr); 893cc71bff1SMichael Lange ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 894cc71bff1SMichael Lange ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 895cc71bff1SMichael Lange ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 896cc71bff1SMichael Lange ierr = ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr); 897cc71bff1SMichael Lange ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 898cc71bff1SMichael Lange if (flg) { 899cc71bff1SMichael Lange ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 900cc71bff1SMichael Lange ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 901cc71bff1SMichael Lange ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 902cc71bff1SMichael Lange ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 903cc71bff1SMichael Lange ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr); 904cc71bff1SMichael Lange } 905cc71bff1SMichael Lange ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 906cc71bff1SMichael Lange ierr = DMPlexGetConeOrientations(dmParallel, &newCones);CHKERRQ(ierr); 907cc71bff1SMichael Lange ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 908cc71bff1SMichael Lange ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 909cc71bff1SMichael Lange ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 910cc71bff1SMichael Lange ierr = PetscLogEventEnd(DMPLEX_DistributeCones,dm,0,0,0);CHKERRQ(ierr); 911cc71bff1SMichael Lange /* Create supports and stratify sieve */ 912cc71bff1SMichael Lange { 913cc71bff1SMichael Lange PetscInt pStart, pEnd; 914cc71bff1SMichael Lange 915cc71bff1SMichael Lange ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 916cc71bff1SMichael Lange ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 917cc71bff1SMichael Lange } 918cc71bff1SMichael Lange ierr = DMPlexSymmetrize(dmParallel);CHKERRQ(ierr); 919cc71bff1SMichael Lange ierr = DMPlexStratify(dmParallel);CHKERRQ(ierr); 920cc71bff1SMichael Lange PetscFunctionReturn(0); 921cc71bff1SMichael Lange } 922cc71bff1SMichael Lange 923cc71bff1SMichael Lange #undef __FUNCT__ 9240df0e737SMichael Lange #define __FUNCT__ "DMPlexDistributeCoordinates" 9250df0e737SMichael Lange PetscErrorCode DMPlexDistributeCoordinates(DM dm, PetscSF migrationSF, DM dmParallel) 9260df0e737SMichael Lange { 9270df0e737SMichael Lange MPI_Comm comm; 9280df0e737SMichael Lange PetscSection originalCoordSection, newCoordSection; 9290df0e737SMichael Lange Vec originalCoordinates, newCoordinates; 9300df0e737SMichael Lange PetscInt bs; 9310df0e737SMichael Lange const char *name; 9320df0e737SMichael Lange const PetscReal *maxCell, *L; 9330df0e737SMichael Lange PetscErrorCode ierr; 9340df0e737SMichael Lange 9350df0e737SMichael Lange PetscFunctionBegin; 9360df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9370df0e737SMichael Lange PetscValidPointer(dmParallel, 3); 9380df0e737SMichael Lange 9390df0e737SMichael Lange ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 9400df0e737SMichael Lange ierr = DMGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 9410df0e737SMichael Lange ierr = DMGetCoordinateSection(dmParallel, &newCoordSection);CHKERRQ(ierr); 9420df0e737SMichael Lange ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 9430df0e737SMichael Lange if (originalCoordinates) { 9440df0e737SMichael Lange ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 9450df0e737SMichael Lange ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 9460df0e737SMichael Lange ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 9470df0e737SMichael Lange 9480df0e737SMichael Lange ierr = DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 9490df0e737SMichael Lange ierr = DMSetCoordinatesLocal(dmParallel, newCoordinates);CHKERRQ(ierr); 9500df0e737SMichael Lange ierr = VecGetBlockSize(originalCoordinates, &bs);CHKERRQ(ierr); 9510df0e737SMichael Lange ierr = VecSetBlockSize(newCoordinates, bs);CHKERRQ(ierr); 9520df0e737SMichael Lange ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 9530df0e737SMichael Lange } 9540df0e737SMichael Lange ierr = DMGetPeriodicity(dm, &maxCell, &L);CHKERRQ(ierr); 9550df0e737SMichael Lange if (L) {ierr = DMSetPeriodicity(dmParallel, maxCell, L);CHKERRQ(ierr);} 9560df0e737SMichael Lange PetscFunctionReturn(0); 9570df0e737SMichael Lange } 9580df0e737SMichael Lange 9590df0e737SMichael Lange #undef __FUNCT__ 9600df0e737SMichael Lange #define __FUNCT__ "DMPlexDistributeLabels" 9610df0e737SMichael Lange PetscErrorCode DMPlexDistributeLabels(DM dm, PetscSF migrationSF, PetscSection partSection, IS part, ISLocalToGlobalMapping renumbering, DM dmParallel) 9620df0e737SMichael Lange { 9630df0e737SMichael Lange DM_Plex *mesh = (DM_Plex*) dm->data; 9640df0e737SMichael Lange DM_Plex *pmesh = (DM_Plex*) (dmParallel)->data; 9650df0e737SMichael Lange MPI_Comm comm; 9660df0e737SMichael Lange PetscMPIInt rank; 9670df0e737SMichael Lange DMLabel next = mesh->labels, newNext = pmesh->labels; 9680df0e737SMichael Lange PetscInt numLabels = 0, l; 9690df0e737SMichael Lange PetscErrorCode ierr; 9700df0e737SMichael Lange 9710df0e737SMichael Lange PetscFunctionBegin; 9720df0e737SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9730df0e737SMichael Lange PetscValidPointer(dmParallel, 6); 9740df0e737SMichael Lange ierr = PetscLogEventBegin(DMPLEX_DistributeLabels,dm,0,0,0);CHKERRQ(ierr); 9750df0e737SMichael Lange ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 9760df0e737SMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 9770df0e737SMichael Lange 9780df0e737SMichael Lange /* Bcast number of labels */ 9790df0e737SMichael Lange while (next) {++numLabels; next = next->next;} 9800df0e737SMichael Lange ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 9810df0e737SMichael Lange next = mesh->labels; 9820df0e737SMichael Lange for (l = 0; l < numLabels; ++l) { 9830df0e737SMichael Lange DMLabel labelNew; 9840df0e737SMichael Lange PetscBool isdepth; 9850df0e737SMichael Lange 9860df0e737SMichael Lange /* Skip "depth" because it is recreated */ 9870df0e737SMichael Lange if (!rank) {ierr = PetscStrcmp(next->name, "depth", &isdepth);CHKERRQ(ierr);} 9880df0e737SMichael Lange ierr = MPI_Bcast(&isdepth, 1, MPIU_BOOL, 0, comm);CHKERRQ(ierr); 9890df0e737SMichael Lange if (isdepth) {if (!rank) next = next->next; continue;} 9900df0e737SMichael Lange ierr = DMLabelDistribute(next, partSection, part, renumbering, &labelNew);CHKERRQ(ierr); 9910df0e737SMichael Lange /* Insert into list */ 9920df0e737SMichael Lange if (newNext) newNext->next = labelNew; 9930df0e737SMichael Lange else pmesh->labels = labelNew; 9940df0e737SMichael Lange newNext = labelNew; 9950df0e737SMichael Lange if (!rank) next = next->next; 9960df0e737SMichael Lange } 9970df0e737SMichael Lange ierr = PetscLogEventEnd(DMPLEX_DistributeLabels,dm,0,0,0);CHKERRQ(ierr); 9980df0e737SMichael Lange PetscFunctionReturn(0); 9990df0e737SMichael Lange } 10000df0e737SMichael Lange 10019734c634SMichael Lange #undef __FUNCT__ 10029734c634SMichael Lange #define __FUNCT__ "DMPlexDistributeSetupHybrid" 10039734c634SMichael Lange PetscErrorCode DMPlexDistributeSetupHybrid(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping renumbering, DM dmParallel) 10049734c634SMichael Lange { 10059734c634SMichael Lange DM_Plex *mesh = (DM_Plex*) dm->data; 10069734c634SMichael Lange DM_Plex *pmesh = (DM_Plex*) (dmParallel)->data; 10079734c634SMichael Lange MPI_Comm comm; 10089734c634SMichael Lange const PetscInt *gpoints; 10099734c634SMichael Lange PetscInt dim, depth, n, d; 10109734c634SMichael Lange PetscErrorCode ierr; 10119734c634SMichael Lange 10129734c634SMichael Lange PetscFunctionBegin; 10139734c634SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10149734c634SMichael Lange PetscValidPointer(dmParallel, 4); 10159734c634SMichael Lange 10169734c634SMichael Lange ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 10179734c634SMichael Lange ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 10189734c634SMichael Lange 10199734c634SMichael Lange /* Setup hybrid structure */ 10209734c634SMichael Lange for (d = 0; d <= dim; ++d) {pmesh->hybridPointMax[d] = mesh->hybridPointMax[d];} 10219734c634SMichael Lange ierr = MPI_Bcast(pmesh->hybridPointMax, dim+1, MPIU_INT, 0, comm);CHKERRQ(ierr); 10229734c634SMichael Lange ierr = ISLocalToGlobalMappingGetSize(renumbering, &n);CHKERRQ(ierr); 10239734c634SMichael Lange ierr = ISLocalToGlobalMappingGetIndices(renumbering, &gpoints);CHKERRQ(ierr); 10249734c634SMichael Lange ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 10259734c634SMichael Lange for (d = 0; d <= dim; ++d) { 10269734c634SMichael Lange PetscInt pmax = pmesh->hybridPointMax[d], newmax = 0, pEnd, stratum[2], p; 10279734c634SMichael Lange 10289734c634SMichael Lange if (pmax < 0) continue; 10299734c634SMichael Lange ierr = DMPlexGetDepthStratum(dm, d > depth ? depth : d, &stratum[0], &stratum[1]);CHKERRQ(ierr); 10309734c634SMichael Lange ierr = DMPlexGetDepthStratum(dmParallel, d, NULL, &pEnd);CHKERRQ(ierr); 10319734c634SMichael Lange ierr = MPI_Bcast(stratum, 2, MPIU_INT, 0, comm);CHKERRQ(ierr); 10329734c634SMichael Lange for (p = 0; p < n; ++p) { 10339734c634SMichael Lange const PetscInt point = gpoints[p]; 10349734c634SMichael Lange 10359734c634SMichael Lange if ((point >= stratum[0]) && (point < stratum[1]) && (point >= pmax)) ++newmax; 10369734c634SMichael Lange } 10379734c634SMichael Lange if (newmax > 0) pmesh->hybridPointMax[d] = pEnd - newmax; 10389734c634SMichael Lange else pmesh->hybridPointMax[d] = -1; 10399734c634SMichael Lange } 10409734c634SMichael Lange ierr = ISLocalToGlobalMappingRestoreIndices(renumbering, &gpoints);CHKERRQ(ierr); 10419734c634SMichael Lange PetscFunctionReturn(0); 10429734c634SMichael Lange } 10430df0e737SMichael Lange 1044a6f36705SMichael Lange #undef __FUNCT__ 1045a6f36705SMichael Lange #define __FUNCT__ "DMPlexDistributeSetupTree" 1046a6f36705SMichael Lange PetscErrorCode DMPlexDistributeSetupTree(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping renumbering, DM dmParallel) 1047a6f36705SMichael Lange { 1048a6f36705SMichael Lange MPI_Comm comm; 1049a6f36705SMichael Lange DM refTree; 1050a6f36705SMichael Lange PetscSection origParentSection, newParentSection; 1051a6f36705SMichael Lange PetscInt *origParents, *origChildIDs; 1052a6f36705SMichael Lange PetscBool flg; 1053a6f36705SMichael Lange PetscErrorCode ierr; 1054a6f36705SMichael Lange 1055a6f36705SMichael Lange PetscFunctionBegin; 1056a6f36705SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1057a6f36705SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 4); 1058a6f36705SMichael Lange ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1059a6f36705SMichael Lange 1060a6f36705SMichael Lange /* Set up tree */ 1061a6f36705SMichael Lange ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr); 1062a6f36705SMichael Lange ierr = DMPlexSetReferenceTree(dmParallel,refTree);CHKERRQ(ierr); 1063a6f36705SMichael Lange ierr = DMPlexGetTree(dm,&origParentSection,&origParents,&origChildIDs,NULL,NULL);CHKERRQ(ierr); 1064a6f36705SMichael Lange if (origParentSection) { 1065a6f36705SMichael Lange PetscInt pStart, pEnd; 1066a6f36705SMichael Lange PetscInt *newParents, *newChildIDs; 1067a6f36705SMichael Lange PetscInt *remoteOffsetsParents, newParentSize; 1068a6f36705SMichael Lange PetscSF parentSF; 1069a6f36705SMichael Lange 1070a6f36705SMichael Lange ierr = DMPlexGetChart(dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 1071a6f36705SMichael Lange ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dmParallel),&newParentSection);CHKERRQ(ierr); 1072a6f36705SMichael Lange ierr = PetscSectionSetChart(newParentSection,pStart,pEnd);CHKERRQ(ierr); 1073a6f36705SMichael Lange ierr = PetscSFDistributeSection(migrationSF, origParentSection, &remoteOffsetsParents, newParentSection);CHKERRQ(ierr); 1074a6f36705SMichael Lange ierr = PetscSFCreateSectionSF(migrationSF, origParentSection, remoteOffsetsParents, newParentSection, &parentSF);CHKERRQ(ierr); 1075a6f36705SMichael Lange ierr = PetscSectionGetStorageSize(newParentSection,&newParentSize);CHKERRQ(ierr); 1076a6f36705SMichael Lange ierr = PetscMalloc2(newParentSize,&newParents,newParentSize,&newChildIDs);CHKERRQ(ierr); 1077a6f36705SMichael Lange ierr = PetscSFBcastBegin(parentSF, MPIU_INT, origParents, newParents);CHKERRQ(ierr); 1078a6f36705SMichael Lange ierr = PetscSFBcastEnd(parentSF, MPIU_INT, origParents, newParents);CHKERRQ(ierr); 1079a6f36705SMichael Lange ierr = PetscSFBcastBegin(parentSF, MPIU_INT, origChildIDs, newChildIDs);CHKERRQ(ierr); 1080a6f36705SMichael Lange ierr = PetscSFBcastEnd(parentSF, MPIU_INT, origChildIDs, newChildIDs);CHKERRQ(ierr); 1081a6f36705SMichael Lange ierr = ISGlobalToLocalMappingApplyBlock(renumbering,IS_GTOLM_MASK, newParentSize, newParents, NULL, newParents);CHKERRQ(ierr); 1082a6f36705SMichael Lange ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-parents_view", &flg);CHKERRQ(ierr); 1083a6f36705SMichael Lange if (flg) { 1084a6f36705SMichael Lange ierr = PetscPrintf(comm, "Serial Parent Section: \n");CHKERRQ(ierr); 1085a6f36705SMichael Lange ierr = PetscSectionView(origParentSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1086a6f36705SMichael Lange ierr = PetscPrintf(comm, "Parallel Parent Section: \n");CHKERRQ(ierr); 1087a6f36705SMichael Lange ierr = PetscSectionView(newParentSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1088a6f36705SMichael Lange ierr = PetscSFView(parentSF, NULL);CHKERRQ(ierr); 1089a6f36705SMichael Lange } 1090a6f36705SMichael Lange ierr = DMPlexSetTree(dmParallel,newParentSection,newParents,newChildIDs);CHKERRQ(ierr); 1091a6f36705SMichael Lange ierr = PetscSectionDestroy(&newParentSection);CHKERRQ(ierr); 1092a6f36705SMichael Lange ierr = PetscFree2(newParents,newChildIDs);CHKERRQ(ierr); 1093a6f36705SMichael Lange ierr = PetscSFDestroy(&parentSF);CHKERRQ(ierr); 1094a6f36705SMichael Lange } 1095a6f36705SMichael Lange PetscFunctionReturn(0); 1096a6f36705SMichael Lange } 10970df0e737SMichael Lange 10980df0e737SMichael Lange #undef __FUNCT__ 10994eca1733SMichael Lange #define __FUNCT__ "DMPlexDistributeSF" 11004eca1733SMichael Lange PetscErrorCode DMPlexDistributeSF(DM dm, PetscSF migrationSF, PetscSection partSection, IS part, PetscSection origPartSection, IS origPart, DM dmParallel) 11014eca1733SMichael Lange { 11024eca1733SMichael Lange DM_Plex *mesh = (DM_Plex*) dm->data; 11034eca1733SMichael Lange DM_Plex *pmesh = (DM_Plex*) (dmParallel)->data; 11044eca1733SMichael Lange PetscMPIInt rank, numProcs; 11054eca1733SMichael Lange MPI_Comm comm; 11064eca1733SMichael Lange PetscErrorCode ierr; 11074eca1733SMichael Lange 11084eca1733SMichael Lange PetscFunctionBegin; 11094eca1733SMichael Lange PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 11104eca1733SMichael Lange PetscValidPointer(dmParallel,7); 11114eca1733SMichael Lange 11124eca1733SMichael Lange /* Create point SF for parallel mesh */ 11134eca1733SMichael Lange ierr = PetscLogEventBegin(DMPLEX_DistributeSF,dm,0,0,0);CHKERRQ(ierr); 11144eca1733SMichael Lange ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 11154eca1733SMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 11164eca1733SMichael Lange ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 11174eca1733SMichael Lange { 11184eca1733SMichael Lange const PetscInt *leaves; 11194eca1733SMichael Lange PetscSFNode *remotePoints, *rowners, *lowners; 11204eca1733SMichael Lange PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 11214eca1733SMichael Lange PetscInt pStart, pEnd; 11224eca1733SMichael Lange 11234eca1733SMichael Lange ierr = DMPlexGetChart(dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 11244eca1733SMichael Lange ierr = PetscSFGetGraph(migrationSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr); 11254eca1733SMichael Lange ierr = PetscMalloc2(numRoots,&rowners,numLeaves,&lowners);CHKERRQ(ierr); 11264eca1733SMichael Lange for (p=0; p<numRoots; p++) { 11274eca1733SMichael Lange rowners[p].rank = -1; 11284eca1733SMichael Lange rowners[p].index = -1; 11294eca1733SMichael Lange } 11304eca1733SMichael Lange if (origPart) { 11314eca1733SMichael Lange /* Make sure points in the original partition are not assigned to other procs */ 11324eca1733SMichael Lange const PetscInt *origPoints; 11334eca1733SMichael Lange 11344eca1733SMichael Lange ierr = ISGetIndices(origPart, &origPoints);CHKERRQ(ierr); 11354eca1733SMichael Lange for (p = 0; p < numProcs; ++p) { 11364eca1733SMichael Lange PetscInt dof, off, d; 11374eca1733SMichael Lange 11384eca1733SMichael Lange ierr = PetscSectionGetDof(origPartSection, p, &dof);CHKERRQ(ierr); 11394eca1733SMichael Lange ierr = PetscSectionGetOffset(origPartSection, p, &off);CHKERRQ(ierr); 11404eca1733SMichael Lange for (d = off; d < off+dof; ++d) { 11414eca1733SMichael Lange rowners[origPoints[d]].rank = p; 11424eca1733SMichael Lange } 11434eca1733SMichael Lange } 11444eca1733SMichael Lange ierr = ISRestoreIndices(origPart, &origPoints);CHKERRQ(ierr); 11454eca1733SMichael Lange } 11464eca1733SMichael Lange ierr = PetscSFBcastBegin(migrationSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 11474eca1733SMichael Lange ierr = PetscSFBcastEnd(migrationSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 11484eca1733SMichael Lange for (p = 0; p < numLeaves; ++p) { 11494eca1733SMichael Lange if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 11504eca1733SMichael Lange lowners[p].rank = rank; 11514eca1733SMichael Lange lowners[p].index = leaves ? leaves[p] : p; 11524eca1733SMichael Lange } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 11534eca1733SMichael Lange lowners[p].rank = -2; 11544eca1733SMichael Lange lowners[p].index = -2; 11554eca1733SMichael Lange } 11564eca1733SMichael Lange } 11574eca1733SMichael Lange for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 11584eca1733SMichael Lange rowners[p].rank = -3; 11594eca1733SMichael Lange rowners[p].index = -3; 11604eca1733SMichael Lange } 11614eca1733SMichael Lange ierr = PetscSFReduceBegin(migrationSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 11624eca1733SMichael Lange ierr = PetscSFReduceEnd(migrationSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 11634eca1733SMichael Lange ierr = PetscSFBcastBegin(migrationSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 11644eca1733SMichael Lange ierr = PetscSFBcastEnd(migrationSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 11654eca1733SMichael Lange for (p = 0; p < numLeaves; ++p) { 11664eca1733SMichael Lange if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 11674eca1733SMichael Lange if (lowners[p].rank != rank) ++numGhostPoints; 11684eca1733SMichael Lange } 11694eca1733SMichael Lange ierr = PetscMalloc1(numGhostPoints, &ghostPoints);CHKERRQ(ierr); 11704eca1733SMichael Lange ierr = PetscMalloc1(numGhostPoints, &remotePoints);CHKERRQ(ierr); 11714eca1733SMichael Lange for (p = 0, gp = 0; p < numLeaves; ++p) { 11724eca1733SMichael Lange if (lowners[p].rank != rank) { 11734eca1733SMichael Lange ghostPoints[gp] = leaves ? leaves[p] : p; 11744eca1733SMichael Lange remotePoints[gp].rank = lowners[p].rank; 11754eca1733SMichael Lange remotePoints[gp].index = lowners[p].index; 11764eca1733SMichael Lange ++gp; 11774eca1733SMichael Lange } 11784eca1733SMichael Lange } 11794eca1733SMichael Lange ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 11804eca1733SMichael Lange ierr = PetscSFSetGraph((dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 11814eca1733SMichael Lange ierr = PetscSFSetFromOptions((dmParallel)->sf);CHKERRQ(ierr); 11824eca1733SMichael Lange } 11834eca1733SMichael Lange pmesh->useCone = mesh->useCone; 11844eca1733SMichael Lange pmesh->useClosure = mesh->useClosure; 11854eca1733SMichael Lange ierr = PetscLogEventEnd(DMPLEX_DistributeSF,dm,0,0,0);CHKERRQ(ierr); 11864eca1733SMichael Lange PetscFunctionReturn(0); 11874eca1733SMichael Lange } 11884eca1733SMichael Lange 11894eca1733SMichael Lange #undef __FUNCT__ 119070034214SMatthew G. Knepley #define __FUNCT__ "DMPlexDistribute" 119170034214SMatthew G. Knepley /*@C 119270034214SMatthew G. Knepley DMPlexDistribute - Distributes the mesh and any associated sections. 119370034214SMatthew G. Knepley 119470034214SMatthew G. Knepley Not Collective 119570034214SMatthew G. Knepley 119670034214SMatthew G. Knepley Input Parameter: 119770034214SMatthew G. Knepley + dm - The original DMPlex object 119870034214SMatthew G. Knepley . partitioner - The partitioning package, or NULL for the default 119970034214SMatthew G. Knepley - overlap - The overlap of partitions, 0 is the default 120070034214SMatthew G. Knepley 120170034214SMatthew G. Knepley Output Parameter: 120270034214SMatthew G. Knepley + sf - The PetscSF used for point distribution 120370034214SMatthew G. Knepley - parallelMesh - The distributed DMPlex object, or NULL 120470034214SMatthew G. Knepley 1205a9c22940SMatthew G. Knepley Note: If the mesh was not distributed, the return value is NULL. 1206a9c22940SMatthew G. Knepley 1207a9c22940SMatthew G. Knepley The user can control the definition of adjacency for the mesh using DMPlexGetAdjacencyUseCone() and 1208a9c22940SMatthew G. Knepley DMPlexSetAdjacencyUseClosure(). They should choose the combination appropriate for the function 1209a9c22940SMatthew G. Knepley representation on the mesh. 121070034214SMatthew G. Knepley 121170034214SMatthew G. Knepley Level: intermediate 121270034214SMatthew G. Knepley 121370034214SMatthew G. Knepley .keywords: mesh, elements 1214a9c22940SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexDistributeByFace(), DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure() 121570034214SMatthew G. Knepley @*/ 121670034214SMatthew G. Knepley PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, PetscSF *sf, DM *dmParallel) 121770034214SMatthew G. Knepley { 121870034214SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data, *pmesh; 121970034214SMatthew G. Knepley MPI_Comm comm; 122070034214SMatthew G. Knepley PetscInt dim, numRemoteRanks; 12214eca1733SMichael Lange IS origCellPart=NULL, origPart=NULL, cellPart, part; 12224eca1733SMichael Lange PetscSection origCellPartSection=NULL, origPartSection=NULL, cellPartSection, partSection; 122370034214SMatthew G. Knepley PetscSFNode *remoteRanks; 1224cc71bff1SMichael Lange PetscSF partSF, pointSF; 122570034214SMatthew G. Knepley ISLocalToGlobalMapping renumbering; 122670034214SMatthew G. Knepley PetscBool flg; 122770034214SMatthew G. Knepley PetscMPIInt rank, numProcs, p; 122870034214SMatthew G. Knepley PetscErrorCode ierr; 122970034214SMatthew G. Knepley 123070034214SMatthew G. Knepley PetscFunctionBegin; 123170034214SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 123270034214SMatthew G. Knepley if (sf) PetscValidPointer(sf,4); 123370034214SMatthew G. Knepley PetscValidPointer(dmParallel,5); 123470034214SMatthew G. Knepley 123570034214SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 123670034214SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 123770034214SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 123870034214SMatthew G. Knepley ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 123970034214SMatthew G. Knepley 124070034214SMatthew G. Knepley *dmParallel = NULL; 124170034214SMatthew G. Knepley if (numProcs == 1) PetscFunctionReturn(0); 124270034214SMatthew G. Knepley 1243c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 124470034214SMatthew G. Knepley /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 124577623264SMatthew G. Knepley ierr = PetscLogEventBegin(PETSCPARTITIONER_Partition,dm,0,0,0);CHKERRQ(ierr); 124677623264SMatthew G. Knepley if (overlap > 1) SETERRQ(comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 124777623264SMatthew G. Knepley ierr = PetscSectionCreate(comm, &cellPartSection);CHKERRQ(ierr); 124877623264SMatthew G. Knepley ierr = PetscSectionCreate(comm, &origCellPartSection);CHKERRQ(ierr); 124977623264SMatthew G. Knepley ierr = PetscPartitionerPartition(mesh->partitioner, dm, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, cellPartSection, &cellPart, origCellPartSection, &origCellPart);CHKERRQ(ierr); 125070034214SMatthew G. Knepley /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 125170034214SMatthew G. Knepley if (!rank) numRemoteRanks = numProcs; 125270034214SMatthew G. Knepley else numRemoteRanks = 0; 125370034214SMatthew G. Knepley ierr = PetscMalloc1(numRemoteRanks, &remoteRanks);CHKERRQ(ierr); 125470034214SMatthew G. Knepley for (p = 0; p < numRemoteRanks; ++p) { 125570034214SMatthew G. Knepley remoteRanks[p].rank = p; 125670034214SMatthew G. Knepley remoteRanks[p].index = 0; 125770034214SMatthew G. Knepley } 125870034214SMatthew G. Knepley ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 125970034214SMatthew G. Knepley ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 126070034214SMatthew G. Knepley ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 126170034214SMatthew G. Knepley if (flg) { 126270034214SMatthew G. Knepley ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 126370034214SMatthew G. Knepley ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 126470034214SMatthew G. Knepley ierr = ISView(cellPart, NULL);CHKERRQ(ierr); 126570034214SMatthew G. Knepley if (origCellPart) { 126670034214SMatthew G. Knepley ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 126770034214SMatthew G. Knepley ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 126870034214SMatthew G. Knepley ierr = ISView(origCellPart, NULL);CHKERRQ(ierr); 126970034214SMatthew G. Knepley } 127070034214SMatthew G. Knepley ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr); 127170034214SMatthew G. Knepley } 127270034214SMatthew G. Knepley /* Close the partition over the mesh */ 127370034214SMatthew G. Knepley ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 127470034214SMatthew G. Knepley /* Create new mesh */ 127570034214SMatthew G. Knepley ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 1276c73cfb54SMatthew G. Knepley ierr = DMSetDimension(*dmParallel, dim);CHKERRQ(ierr); 127770034214SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 127870034214SMatthew G. Knepley pmesh = (DM_Plex*) (*dmParallel)->data; 12794eca1733SMichael Lange pmesh->useAnchors = mesh->useAnchors; 12804eca1733SMichael Lange 128170034214SMatthew G. Knepley /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 128270034214SMatthew G. Knepley ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 128370034214SMatthew G. Knepley if (flg) { 128470034214SMatthew G. Knepley ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 128570034214SMatthew G. Knepley ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 128670034214SMatthew G. Knepley ierr = ISView(part, NULL);CHKERRQ(ierr); 128770034214SMatthew G. Knepley ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr); 128870034214SMatthew G. Knepley ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 128970034214SMatthew G. Knepley ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr); 129070034214SMatthew G. Knepley } 129177623264SMatthew G. Knepley ierr = PetscLogEventEnd(PETSCPARTITIONER_Partition,dm,0,0,0);CHKERRQ(ierr); 129270034214SMatthew G. Knepley 1293cc71bff1SMichael Lange ierr = DMPlexDistributeCones(dm, pointSF, renumbering, *dmParallel);CHKERRQ(ierr); 12940df0e737SMichael Lange ierr = DMPlexDistributeCoordinates(dm, pointSF, *dmParallel);CHKERRQ(ierr); 12950df0e737SMichael Lange ierr = DMPlexDistributeLabels(dm, pointSF, partSection, part, renumbering, *dmParallel);CHKERRQ(ierr); 12969734c634SMichael Lange ierr = DMPlexDistributeSetupHybrid(dm, pointSF, renumbering, *dmParallel);CHKERRQ(ierr); 1297a6f36705SMichael Lange ierr = DMPlexDistributeSetupTree(dm, pointSF, renumbering, *dmParallel);CHKERRQ(ierr); 129870034214SMatthew G. Knepley if (origCellPart) { 129970034214SMatthew G. Knepley ierr = DMPlexCreatePartitionClosure(dm, origCellPartSection, origCellPart, &origPartSection, &origPart);CHKERRQ(ierr); 13004eca1733SMichael Lange } 13014eca1733SMichael Lange ierr = DMPlexDistributeSF(dm, pointSF, partSection, part, origPartSection, origPart, *dmParallel);CHKERRQ(ierr); 130270034214SMatthew G. Knepley 1303bf5244c7SMatthew G. Knepley /* Cleanup Partition */ 1304bf5244c7SMatthew G. Knepley ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 1305bf5244c7SMatthew G. Knepley ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 1306bf5244c7SMatthew G. Knepley ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 1307bf5244c7SMatthew G. Knepley ierr = ISDestroy(&part);CHKERRQ(ierr); 13084eca1733SMichael Lange ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 13094eca1733SMichael Lange ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 13104eca1733SMichael Lange if (origCellPart) { 13114eca1733SMichael Lange ierr = PetscSectionDestroy(&origPartSection);CHKERRQ(ierr); 13124eca1733SMichael Lange ierr = ISDestroy(&origPart);CHKERRQ(ierr); 13134eca1733SMichael Lange ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 13144eca1733SMichael Lange ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 13154eca1733SMichael Lange } 131686719b60SMatthew G. Knepley /* Copy BC */ 131786719b60SMatthew G. Knepley ierr = DMPlexCopyBoundary(dm, *dmParallel);CHKERRQ(ierr); 131870034214SMatthew G. Knepley /* Cleanup */ 131970034214SMatthew G. Knepley if (sf) {*sf = pointSF;} 132070034214SMatthew G. Knepley else {ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr);} 132170034214SMatthew G. Knepley ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 132270034214SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 132370034214SMatthew G. Knepley PetscFunctionReturn(0); 132470034214SMatthew G. Knepley } 1325