xref: /petsc/src/dm/impls/plex/plexdistribute.c (revision e540f424d93a01896fc8be44e39d689b2a649fd9)
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