xref: /petsc/src/dm/impls/plex/plexdistribute.c (revision 9852e1235e6de1345fdd93ba94fdd27144d16762)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>    /*I      "petscdmplex.h"   I*/
2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h>   /*I      "petscdmlabel.h"  I*/
370034214SMatthew G. Knepley 
470034214SMatthew G. Knepley /*@
570034214SMatthew G. Knepley   DMPlexSetAdjacencyUseCone - Define adjacency in the mesh using either the cone or the support first
670034214SMatthew G. Knepley 
770034214SMatthew G. Knepley   Input Parameters:
870034214SMatthew G. Knepley + dm      - The DM object
970034214SMatthew G. Knepley - useCone - Flag to use the cone first
1070034214SMatthew G. Knepley 
1170034214SMatthew G. Knepley   Level: intermediate
1270034214SMatthew G. Knepley 
1370034214SMatthew G. Knepley   Notes:
1470034214SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
154b6b44bdSMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
1670034214SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
1770034214SMatthew G. Knepley 
1870034214SMatthew G. Knepley .seealso: DMPlexGetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure(), DMPlexGetAdjacencyUseClosure(), DMPlexDistribute(), DMPlexPreallocateOperator()
1970034214SMatthew G. Knepley @*/
2070034214SMatthew G. Knepley PetscErrorCode DMPlexSetAdjacencyUseCone(DM dm, PetscBool useCone)
2170034214SMatthew G. Knepley {
2270034214SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *) dm->data;
2370034214SMatthew G. Knepley 
2470034214SMatthew G. Knepley   PetscFunctionBegin;
2570034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2670034214SMatthew G. Knepley   mesh->useCone = useCone;
2770034214SMatthew G. Knepley   PetscFunctionReturn(0);
2870034214SMatthew G. Knepley }
2970034214SMatthew G. Knepley 
3070034214SMatthew G. Knepley /*@
3170034214SMatthew G. Knepley   DMPlexGetAdjacencyUseCone - Query whether adjacency in the mesh uses the cone or the support first
3270034214SMatthew G. Knepley 
3370034214SMatthew G. Knepley   Input Parameter:
3470034214SMatthew G. Knepley . dm      - The DM object
3570034214SMatthew G. Knepley 
3670034214SMatthew G. Knepley   Output Parameter:
3770034214SMatthew G. Knepley . useCone - Flag to use the cone first
3870034214SMatthew G. Knepley 
3970034214SMatthew G. Knepley   Level: intermediate
4070034214SMatthew G. Knepley 
4170034214SMatthew G. Knepley   Notes:
4270034214SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
434b6b44bdSMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
4470034214SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
4570034214SMatthew G. Knepley 
4670034214SMatthew G. Knepley .seealso: DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure(), DMPlexGetAdjacencyUseClosure(), DMPlexDistribute(), DMPlexPreallocateOperator()
4770034214SMatthew G. Knepley @*/
4870034214SMatthew G. Knepley PetscErrorCode DMPlexGetAdjacencyUseCone(DM dm, PetscBool *useCone)
4970034214SMatthew G. Knepley {
5070034214SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *) dm->data;
5170034214SMatthew G. Knepley 
5270034214SMatthew G. Knepley   PetscFunctionBegin;
5370034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5470034214SMatthew G. Knepley   PetscValidIntPointer(useCone, 2);
5570034214SMatthew G. Knepley   *useCone = mesh->useCone;
5670034214SMatthew G. Knepley   PetscFunctionReturn(0);
5770034214SMatthew G. Knepley }
5870034214SMatthew G. Knepley 
5970034214SMatthew G. Knepley /*@
6070034214SMatthew G. Knepley   DMPlexSetAdjacencyUseClosure - Define adjacency in the mesh using the transitive closure
6170034214SMatthew G. Knepley 
6270034214SMatthew G. Knepley   Input Parameters:
6370034214SMatthew G. Knepley + dm      - The DM object
6470034214SMatthew G. Knepley - useClosure - Flag to use the closure
6570034214SMatthew G. Knepley 
6670034214SMatthew G. Knepley   Level: intermediate
6770034214SMatthew G. Knepley 
6870034214SMatthew G. Knepley   Notes:
6970034214SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
704b6b44bdSMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
7170034214SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
7270034214SMatthew G. Knepley 
7370034214SMatthew G. Knepley .seealso: DMPlexGetAdjacencyUseClosure(), DMPlexSetAdjacencyUseCone(), DMPlexGetAdjacencyUseCone(), DMPlexDistribute(), DMPlexPreallocateOperator()
7470034214SMatthew G. Knepley @*/
7570034214SMatthew G. Knepley PetscErrorCode DMPlexSetAdjacencyUseClosure(DM dm, PetscBool useClosure)
7670034214SMatthew G. Knepley {
7770034214SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *) dm->data;
7870034214SMatthew G. Knepley 
7970034214SMatthew G. Knepley   PetscFunctionBegin;
8070034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8170034214SMatthew G. Knepley   mesh->useClosure = useClosure;
8270034214SMatthew G. Knepley   PetscFunctionReturn(0);
8370034214SMatthew G. Knepley }
8470034214SMatthew G. Knepley 
8570034214SMatthew G. Knepley /*@
8670034214SMatthew G. Knepley   DMPlexGetAdjacencyUseClosure - Query whether adjacency in the mesh uses the transitive closure
8770034214SMatthew G. Knepley 
8870034214SMatthew G. Knepley   Input Parameter:
8970034214SMatthew G. Knepley . dm      - The DM object
9070034214SMatthew G. Knepley 
9170034214SMatthew G. Knepley   Output Parameter:
9270034214SMatthew G. Knepley . useClosure - Flag to use the closure
9370034214SMatthew G. Knepley 
9470034214SMatthew G. Knepley   Level: intermediate
9570034214SMatthew G. Knepley 
9670034214SMatthew G. Knepley   Notes:
9770034214SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
984b6b44bdSMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
9970034214SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
10070034214SMatthew G. Knepley 
10170034214SMatthew G. Knepley .seealso: DMPlexSetAdjacencyUseClosure(), DMPlexSetAdjacencyUseCone(), DMPlexGetAdjacencyUseCone(), DMPlexDistribute(), DMPlexPreallocateOperator()
10270034214SMatthew G. Knepley @*/
10370034214SMatthew G. Knepley PetscErrorCode DMPlexGetAdjacencyUseClosure(DM dm, PetscBool *useClosure)
10470034214SMatthew G. Knepley {
10570034214SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *) dm->data;
10670034214SMatthew G. Knepley 
10770034214SMatthew G. Knepley   PetscFunctionBegin;
10870034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10970034214SMatthew G. Knepley   PetscValidIntPointer(useClosure, 2);
11070034214SMatthew G. Knepley   *useClosure = mesh->useClosure;
11170034214SMatthew G. Knepley   PetscFunctionReturn(0);
11270034214SMatthew G. Knepley }
11370034214SMatthew G. Knepley 
1148b0b4c70SToby Isaac /*@
115a17985deSToby Isaac   DMPlexSetAdjacencyUseAnchors - Define adjacency in the mesh using the point-to-point constraints.
1168b0b4c70SToby Isaac 
1178b0b4c70SToby Isaac   Input Parameters:
1188b0b4c70SToby Isaac + dm      - The DM object
1195b317d89SToby 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.
1208b0b4c70SToby Isaac 
1218b0b4c70SToby Isaac   Level: intermediate
1228b0b4c70SToby Isaac 
123a17985deSToby Isaac .seealso: DMPlexGetAdjacencyUseClosure(), DMPlexSetAdjacencyUseCone(), DMPlexGetAdjacencyUseCone(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexSetAnchors()
1248b0b4c70SToby Isaac @*/
1255b317d89SToby Isaac PetscErrorCode DMPlexSetAdjacencyUseAnchors(DM dm, PetscBool useAnchors)
1268b0b4c70SToby Isaac {
1278b0b4c70SToby Isaac   DM_Plex *mesh = (DM_Plex *) dm->data;
1288b0b4c70SToby Isaac 
1298b0b4c70SToby Isaac   PetscFunctionBegin;
1308b0b4c70SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1315b317d89SToby Isaac   mesh->useAnchors = useAnchors;
1328b0b4c70SToby Isaac   PetscFunctionReturn(0);
1338b0b4c70SToby Isaac }
1348b0b4c70SToby Isaac 
1358b0b4c70SToby Isaac /*@
136a17985deSToby Isaac   DMPlexGetAdjacencyUseAnchors - Query whether adjacency in the mesh uses the point-to-point constraints.
1378b0b4c70SToby Isaac 
1388b0b4c70SToby Isaac   Input Parameter:
1398b0b4c70SToby Isaac . dm      - The DM object
1408b0b4c70SToby Isaac 
1418b0b4c70SToby Isaac   Output Parameter:
1425b317d89SToby 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.
1438b0b4c70SToby Isaac 
1448b0b4c70SToby Isaac   Level: intermediate
1458b0b4c70SToby Isaac 
146a17985deSToby Isaac .seealso: DMPlexSetAdjacencyUseAnchors(), DMPlexSetAdjacencyUseCone(), DMPlexGetAdjacencyUseCone(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexSetAnchors()
1478b0b4c70SToby Isaac @*/
1485b317d89SToby Isaac PetscErrorCode DMPlexGetAdjacencyUseAnchors(DM dm, PetscBool *useAnchors)
1498b0b4c70SToby Isaac {
1508b0b4c70SToby Isaac   DM_Plex *mesh = (DM_Plex *) dm->data;
1518b0b4c70SToby Isaac 
1528b0b4c70SToby Isaac   PetscFunctionBegin;
1538b0b4c70SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1545b317d89SToby Isaac   PetscValidIntPointer(useAnchors, 2);
1555b317d89SToby Isaac   *useAnchors = mesh->useAnchors;
1568b0b4c70SToby Isaac   PetscFunctionReturn(0);
1578b0b4c70SToby Isaac }
1588b0b4c70SToby Isaac 
15970034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Cone_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[])
16070034214SMatthew G. Knepley {
16170034214SMatthew G. Knepley   const PetscInt *cone = NULL;
16270034214SMatthew G. Knepley   PetscInt        numAdj = 0, maxAdjSize = *adjSize, coneSize, c;
16370034214SMatthew G. Knepley   PetscErrorCode  ierr;
16470034214SMatthew G. Knepley 
16570034214SMatthew G. Knepley   PetscFunctionBeginHot;
16670034214SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
16770034214SMatthew G. Knepley   ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
1684b6b44bdSMatthew G. Knepley   for (c = 0; c <= coneSize; ++c) {
1694b6b44bdSMatthew G. Knepley     const PetscInt  point   = !c ? p : cone[c-1];
17070034214SMatthew G. Knepley     const PetscInt *support = NULL;
17170034214SMatthew G. Knepley     PetscInt        supportSize, s, q;
17270034214SMatthew G. Knepley 
1734b6b44bdSMatthew G. Knepley     ierr = DMPlexGetSupportSize(dm, point, &supportSize);CHKERRQ(ierr);
1744b6b44bdSMatthew G. Knepley     ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr);
17570034214SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
176527e7439SSatish Balay       for (q = 0; q < numAdj || ((void)(adj[numAdj++] = support[s]),0); ++q) {
17770034214SMatthew G. Knepley         if (support[s] == adj[q]) break;
17870034214SMatthew G. Knepley       }
17970034214SMatthew G. Knepley       if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
18070034214SMatthew G. Knepley     }
18170034214SMatthew G. Knepley   }
18270034214SMatthew G. Knepley   *adjSize = numAdj;
18370034214SMatthew G. Knepley   PetscFunctionReturn(0);
18470034214SMatthew G. Knepley }
18570034214SMatthew G. Knepley 
18670034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Support_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[])
18770034214SMatthew G. Knepley {
18870034214SMatthew G. Knepley   const PetscInt *support = NULL;
18970034214SMatthew G. Knepley   PetscInt        numAdj   = 0, maxAdjSize = *adjSize, supportSize, s;
19070034214SMatthew G. Knepley   PetscErrorCode  ierr;
19170034214SMatthew G. Knepley 
19270034214SMatthew G. Knepley   PetscFunctionBeginHot;
19370034214SMatthew G. Knepley   ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
19470034214SMatthew G. Knepley   ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr);
1954b6b44bdSMatthew G. Knepley   for (s = 0; s <= supportSize; ++s) {
1964b6b44bdSMatthew G. Knepley     const PetscInt  point = !s ? p : support[s-1];
19770034214SMatthew G. Knepley     const PetscInt *cone  = NULL;
19870034214SMatthew G. Knepley     PetscInt        coneSize, c, q;
19970034214SMatthew G. Knepley 
2004b6b44bdSMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr);
2014b6b44bdSMatthew G. Knepley     ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
20270034214SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
203527e7439SSatish Balay       for (q = 0; q < numAdj || ((void)(adj[numAdj++] = cone[c]),0); ++q) {
20470034214SMatthew G. Knepley         if (cone[c] == adj[q]) break;
20570034214SMatthew G. Knepley       }
20670034214SMatthew G. Knepley       if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
20770034214SMatthew G. Knepley     }
20870034214SMatthew G. Knepley   }
20970034214SMatthew G. Knepley   *adjSize = numAdj;
21070034214SMatthew G. Knepley   PetscFunctionReturn(0);
21170034214SMatthew G. Knepley }
21270034214SMatthew G. Knepley 
21370034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Transitive_Internal(DM dm, PetscInt p, PetscBool useClosure, PetscInt *adjSize, PetscInt adj[])
21470034214SMatthew G. Knepley {
21570034214SMatthew G. Knepley   PetscInt      *star = NULL;
21670034214SMatthew G. Knepley   PetscInt       numAdj = 0, maxAdjSize = *adjSize, starSize, s;
21770034214SMatthew G. Knepley   PetscErrorCode ierr;
21870034214SMatthew G. Knepley 
21970034214SMatthew G. Knepley   PetscFunctionBeginHot;
22070034214SMatthew G. Knepley   ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, &star);CHKERRQ(ierr);
22170034214SMatthew G. Knepley   for (s = 0; s < starSize*2; s += 2) {
22270034214SMatthew G. Knepley     const PetscInt *closure = NULL;
22370034214SMatthew G. Knepley     PetscInt        closureSize, c, q;
22470034214SMatthew G. Knepley 
22570034214SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr);
22670034214SMatthew G. Knepley     for (c = 0; c < closureSize*2; c += 2) {
227527e7439SSatish Balay       for (q = 0; q < numAdj || ((void)(adj[numAdj++] = closure[c]),0); ++q) {
22870034214SMatthew G. Knepley         if (closure[c] == adj[q]) break;
22970034214SMatthew G. Knepley       }
23070034214SMatthew G. Knepley       if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
23170034214SMatthew G. Knepley     }
23270034214SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr);
23370034214SMatthew G. Knepley   }
23470034214SMatthew G. Knepley   ierr = DMPlexRestoreTransitiveClosure(dm, p, useClosure, &starSize, &star);CHKERRQ(ierr);
23570034214SMatthew G. Knepley   *adjSize = numAdj;
23670034214SMatthew G. Knepley   PetscFunctionReturn(0);
23770034214SMatthew G. Knepley }
23870034214SMatthew G. Knepley 
2395b317d89SToby Isaac PetscErrorCode DMPlexGetAdjacency_Internal(DM dm, PetscInt p, PetscBool useCone, PetscBool useTransitiveClosure, PetscBool useAnchors, PetscInt *adjSize, PetscInt *adj[])
24070034214SMatthew G. Knepley {
24179bad331SMatthew G. Knepley   static PetscInt asiz = 0;
2428b0b4c70SToby Isaac   PetscInt maxAnchors = 1;
2438b0b4c70SToby Isaac   PetscInt aStart = -1, aEnd = -1;
2448b0b4c70SToby Isaac   PetscInt maxAdjSize;
2458b0b4c70SToby Isaac   PetscSection aSec = NULL;
2468b0b4c70SToby Isaac   IS aIS = NULL;
2478b0b4c70SToby Isaac   const PetscInt *anchors;
24870034214SMatthew G. Knepley   PetscErrorCode  ierr;
24970034214SMatthew G. Knepley 
25070034214SMatthew G. Knepley   PetscFunctionBeginHot;
2515b317d89SToby Isaac   if (useAnchors) {
252a17985deSToby Isaac     ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr);
2538b0b4c70SToby Isaac     if (aSec) {
2548b0b4c70SToby Isaac       ierr = PetscSectionGetMaxDof(aSec,&maxAnchors);CHKERRQ(ierr);
25524c766afSToby Isaac       maxAnchors = PetscMax(1,maxAnchors);
2568b0b4c70SToby Isaac       ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr);
2578b0b4c70SToby Isaac       ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr);
2588b0b4c70SToby Isaac     }
2598b0b4c70SToby Isaac   }
26079bad331SMatthew G. Knepley   if (!*adj) {
26124c766afSToby Isaac     PetscInt depth, coneSeries, supportSeries, maxC, maxS, pStart, pEnd;
26279bad331SMatthew G. Knepley 
26324c766afSToby Isaac     ierr  = DMPlexGetChart(dm, &pStart,&pEnd);CHKERRQ(ierr);
26479bad331SMatthew G. Knepley     ierr  = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
26524c766afSToby Isaac     ierr  = DMPlexGetMaxSizes(dm, &maxC, &maxS);CHKERRQ(ierr);
26624c766afSToby Isaac     coneSeries    = (maxC > 1) ? ((PetscPowInt(maxC,depth+1)-1)/(maxC-1)) : depth+1;
26724c766afSToby Isaac     supportSeries = (maxS > 1) ? ((PetscPowInt(maxS,depth+1)-1)/(maxS-1)) : depth+1;
26824c766afSToby Isaac     asiz  = PetscMax(PetscPowInt(maxS,depth)*coneSeries,PetscPowInt(maxC,depth)*supportSeries);
2698b0b4c70SToby Isaac     asiz *= maxAnchors;
27024c766afSToby Isaac     asiz  = PetscMin(asiz,pEnd-pStart);
27179bad331SMatthew G. Knepley     ierr  = PetscMalloc1(asiz,adj);CHKERRQ(ierr);
27279bad331SMatthew G. Knepley   }
27379bad331SMatthew G. Knepley   if (*adjSize < 0) *adjSize = asiz;
2748b0b4c70SToby Isaac   maxAdjSize = *adjSize;
27570034214SMatthew G. Knepley   if (useTransitiveClosure) {
27679bad331SMatthew G. Knepley     ierr = DMPlexGetAdjacency_Transitive_Internal(dm, p, useCone, adjSize, *adj);CHKERRQ(ierr);
27770034214SMatthew G. Knepley   } else if (useCone) {
27879bad331SMatthew G. Knepley     ierr = DMPlexGetAdjacency_Cone_Internal(dm, p, adjSize, *adj);CHKERRQ(ierr);
27970034214SMatthew G. Knepley   } else {
28079bad331SMatthew G. Knepley     ierr = DMPlexGetAdjacency_Support_Internal(dm, p, adjSize, *adj);CHKERRQ(ierr);
28170034214SMatthew G. Knepley   }
2825b317d89SToby Isaac   if (useAnchors && aSec) {
2838b0b4c70SToby Isaac     PetscInt origSize = *adjSize;
2848b0b4c70SToby Isaac     PetscInt numAdj = origSize;
2858b0b4c70SToby Isaac     PetscInt i = 0, j;
2868b0b4c70SToby Isaac     PetscInt *orig = *adj;
2878b0b4c70SToby Isaac 
2888b0b4c70SToby Isaac     while (i < origSize) {
2898b0b4c70SToby Isaac       PetscInt p = orig[i];
2908b0b4c70SToby Isaac       PetscInt aDof = 0;
2918b0b4c70SToby Isaac 
2928b0b4c70SToby Isaac       if (p >= aStart && p < aEnd) {
2938b0b4c70SToby Isaac         ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr);
2948b0b4c70SToby Isaac       }
2958b0b4c70SToby Isaac       if (aDof) {
2968b0b4c70SToby Isaac         PetscInt aOff;
2978b0b4c70SToby Isaac         PetscInt s, q;
2988b0b4c70SToby Isaac 
2998b0b4c70SToby Isaac         for (j = i + 1; j < numAdj; j++) {
3008b0b4c70SToby Isaac           orig[j - 1] = orig[j];
3018b0b4c70SToby Isaac         }
3028b0b4c70SToby Isaac         origSize--;
3038b0b4c70SToby Isaac         numAdj--;
3048b0b4c70SToby Isaac         ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr);
3058b0b4c70SToby Isaac         for (s = 0; s < aDof; ++s) {
306527e7439SSatish Balay           for (q = 0; q < numAdj || ((void)(orig[numAdj++] = anchors[aOff+s]),0); ++q) {
3078b0b4c70SToby Isaac             if (anchors[aOff+s] == orig[q]) break;
3088b0b4c70SToby Isaac           }
3098b0b4c70SToby Isaac           if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
3108b0b4c70SToby Isaac         }
3118b0b4c70SToby Isaac       }
3128b0b4c70SToby Isaac       else {
3138b0b4c70SToby Isaac         i++;
3148b0b4c70SToby Isaac       }
3158b0b4c70SToby Isaac     }
3168b0b4c70SToby Isaac     *adjSize = numAdj;
3178b0b4c70SToby Isaac     ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);
3188b0b4c70SToby Isaac   }
31970034214SMatthew G. Knepley   PetscFunctionReturn(0);
32070034214SMatthew G. Knepley }
32170034214SMatthew G. Knepley 
32270034214SMatthew G. Knepley /*@
32370034214SMatthew G. Knepley   DMPlexGetAdjacency - Return all points adjacent to the given point
32470034214SMatthew G. Knepley 
32570034214SMatthew G. Knepley   Input Parameters:
32670034214SMatthew G. Knepley + dm - The DM object
32770034214SMatthew G. Knepley . p  - The point
32870034214SMatthew G. Knepley . adjSize - The maximum size of adj if it is non-NULL, or PETSC_DETERMINE
32970034214SMatthew G. Knepley - adj - Either NULL so that the array is allocated, or an existing array with size adjSize
33070034214SMatthew G. Knepley 
33170034214SMatthew G. Knepley   Output Parameters:
33270034214SMatthew G. Knepley + adjSize - The number of adjacent points
33370034214SMatthew G. Knepley - adj - The adjacent points
33470034214SMatthew G. Knepley 
33570034214SMatthew G. Knepley   Level: advanced
33670034214SMatthew G. Knepley 
33770034214SMatthew G. Knepley   Notes: The user must PetscFree the adj array if it was not passed in.
33870034214SMatthew G. Knepley 
33970034214SMatthew G. Knepley .seealso: DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure(), DMPlexDistribute(), DMCreateMatrix(), DMPlexPreallocateOperator()
34070034214SMatthew G. Knepley @*/
34170034214SMatthew G. Knepley PetscErrorCode DMPlexGetAdjacency(DM dm, PetscInt p, PetscInt *adjSize, PetscInt *adj[])
34270034214SMatthew G. Knepley {
34370034214SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex *) dm->data;
34470034214SMatthew G. Knepley   PetscErrorCode ierr;
34570034214SMatthew G. Knepley 
34670034214SMatthew G. Knepley   PetscFunctionBeginHot;
34770034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34870034214SMatthew G. Knepley   PetscValidPointer(adjSize,3);
34970034214SMatthew G. Knepley   PetscValidPointer(adj,4);
3505b317d89SToby Isaac   ierr = DMPlexGetAdjacency_Internal(dm, p, mesh->useCone, mesh->useClosure, mesh->useAnchors, adjSize, adj);CHKERRQ(ierr);
35170034214SMatthew G. Knepley   PetscFunctionReturn(0);
35270034214SMatthew G. Knepley }
35308633170SToby Isaac 
354b0a623aaSMatthew G. Knepley /*@
355b0a623aaSMatthew G. Knepley   DMPlexCreateTwoSidedProcessSF - Create an SF which just has process connectivity
356b0a623aaSMatthew G. Knepley 
357b0a623aaSMatthew G. Knepley   Collective on DM
358b0a623aaSMatthew G. Knepley 
359b0a623aaSMatthew G. Knepley   Input Parameters:
360b0a623aaSMatthew G. Knepley + dm      - The DM
361b0a623aaSMatthew G. Knepley - sfPoint - The PetscSF which encodes point connectivity
362b0a623aaSMatthew G. Knepley 
363b0a623aaSMatthew G. Knepley   Output Parameters:
364b0a623aaSMatthew G. Knepley + processRanks - A list of process neighbors, or NULL
365b0a623aaSMatthew G. Knepley - sfProcess    - An SF encoding the two-sided process connectivity, or NULL
366b0a623aaSMatthew G. Knepley 
367b0a623aaSMatthew G. Knepley   Level: developer
368b0a623aaSMatthew G. Knepley 
369b0a623aaSMatthew G. Knepley .seealso: PetscSFCreate(), DMPlexCreateProcessSF()
370b0a623aaSMatthew G. Knepley @*/
371b0a623aaSMatthew G. Knepley PetscErrorCode DMPlexCreateTwoSidedProcessSF(DM dm, PetscSF sfPoint, PetscSection rootRankSection, IS rootRanks, PetscSection leafRankSection, IS leafRanks, IS *processRanks, PetscSF *sfProcess)
372b0a623aaSMatthew G. Knepley {
373b0a623aaSMatthew G. Knepley   const PetscSFNode *remotePoints;
374b0a623aaSMatthew G. Knepley   PetscInt          *localPointsNew;
375b0a623aaSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
376b0a623aaSMatthew G. Knepley   const PetscInt    *nranks;
377b0a623aaSMatthew G. Knepley   PetscInt          *ranksNew;
378b0a623aaSMatthew G. Knepley   PetscBT            neighbors;
379b0a623aaSMatthew G. Knepley   PetscInt           pStart, pEnd, p, numLeaves, l, numNeighbors, n;
380*9852e123SBarry Smith   PetscMPIInt        size, proc, rank;
381b0a623aaSMatthew G. Knepley   PetscErrorCode     ierr;
382b0a623aaSMatthew G. Knepley 
383b0a623aaSMatthew G. Knepley   PetscFunctionBegin;
384b0a623aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
385b0a623aaSMatthew G. Knepley   PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2);
386b0a623aaSMatthew G. Knepley   if (processRanks) {PetscValidPointer(processRanks, 3);}
387b0a623aaSMatthew G. Knepley   if (sfProcess)    {PetscValidPointer(sfProcess, 4);}
388*9852e123SBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRQ(ierr);
389b0a623aaSMatthew G. Knepley   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr);
390b0a623aaSMatthew G. Knepley   ierr = PetscSFGetGraph(sfPoint, NULL, &numLeaves, NULL, &remotePoints);CHKERRQ(ierr);
391*9852e123SBarry Smith   ierr = PetscBTCreate(size, &neighbors);CHKERRQ(ierr);
392*9852e123SBarry Smith   ierr = PetscBTMemzero(size, neighbors);CHKERRQ(ierr);
393b0a623aaSMatthew G. Knepley   /* Compute root-to-leaf process connectivity */
394b0a623aaSMatthew G. Knepley   ierr = PetscSectionGetChart(rootRankSection, &pStart, &pEnd);CHKERRQ(ierr);
395b0a623aaSMatthew G. Knepley   ierr = ISGetIndices(rootRanks, &nranks);CHKERRQ(ierr);
396b0a623aaSMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
397b0a623aaSMatthew G. Knepley     PetscInt ndof, noff, n;
398b0a623aaSMatthew G. Knepley 
399b0a623aaSMatthew G. Knepley     ierr = PetscSectionGetDof(rootRankSection, p, &ndof);CHKERRQ(ierr);
400b0a623aaSMatthew G. Knepley     ierr = PetscSectionGetOffset(rootRankSection, p, &noff);CHKERRQ(ierr);
401302440fdSBarry Smith     for (n = 0; n < ndof; ++n) {ierr = PetscBTSet(neighbors, nranks[noff+n]);CHKERRQ(ierr);}
402b0a623aaSMatthew G. Knepley   }
403b0a623aaSMatthew G. Knepley   ierr = ISRestoreIndices(rootRanks, &nranks);CHKERRQ(ierr);
404b0a623aaSMatthew G. Knepley   /* Compute leaf-to-neighbor process connectivity */
405b0a623aaSMatthew G. Knepley   ierr = PetscSectionGetChart(leafRankSection, &pStart, &pEnd);CHKERRQ(ierr);
406b0a623aaSMatthew G. Knepley   ierr = ISGetIndices(leafRanks, &nranks);CHKERRQ(ierr);
407b0a623aaSMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
408b0a623aaSMatthew G. Knepley     PetscInt ndof, noff, n;
409b0a623aaSMatthew G. Knepley 
410b0a623aaSMatthew G. Knepley     ierr = PetscSectionGetDof(leafRankSection, p, &ndof);CHKERRQ(ierr);
411b0a623aaSMatthew G. Knepley     ierr = PetscSectionGetOffset(leafRankSection, p, &noff);CHKERRQ(ierr);
412302440fdSBarry Smith     for (n = 0; n < ndof; ++n) {ierr = PetscBTSet(neighbors, nranks[noff+n]);CHKERRQ(ierr);}
413b0a623aaSMatthew G. Knepley   }
414b0a623aaSMatthew G. Knepley   ierr = ISRestoreIndices(leafRanks, &nranks);CHKERRQ(ierr);
415b0a623aaSMatthew G. Knepley   /* Compute leaf-to-root process connectivity */
416b0a623aaSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {PetscBTSet(neighbors, remotePoints[l].rank);}
417b0a623aaSMatthew G. Knepley   /* Calculate edges */
418b0a623aaSMatthew G. Knepley   PetscBTClear(neighbors, rank);
419*9852e123SBarry Smith   for(proc = 0, numNeighbors = 0; proc < size; ++proc) {if (PetscBTLookup(neighbors, proc)) ++numNeighbors;}
420b0a623aaSMatthew G. Knepley   ierr = PetscMalloc1(numNeighbors, &ranksNew);CHKERRQ(ierr);
421b0a623aaSMatthew G. Knepley   ierr = PetscMalloc1(numNeighbors, &localPointsNew);CHKERRQ(ierr);
422b0a623aaSMatthew G. Knepley   ierr = PetscMalloc1(numNeighbors, &remotePointsNew);CHKERRQ(ierr);
423*9852e123SBarry Smith   for(proc = 0, n = 0; proc < size; ++proc) {
424b0a623aaSMatthew G. Knepley     if (PetscBTLookup(neighbors, proc)) {
425b0a623aaSMatthew G. Knepley       ranksNew[n]              = proc;
426b0a623aaSMatthew G. Knepley       localPointsNew[n]        = proc;
427b0a623aaSMatthew G. Knepley       remotePointsNew[n].index = rank;
428b0a623aaSMatthew G. Knepley       remotePointsNew[n].rank  = proc;
429b0a623aaSMatthew G. Knepley       ++n;
430b0a623aaSMatthew G. Knepley     }
431b0a623aaSMatthew G. Knepley   }
432b0a623aaSMatthew G. Knepley   ierr = PetscBTDestroy(&neighbors);CHKERRQ(ierr);
433b0a623aaSMatthew G. Knepley   if (processRanks) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numNeighbors, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);}
434b0a623aaSMatthew G. Knepley   else              {ierr = PetscFree(ranksNew);CHKERRQ(ierr);}
435b0a623aaSMatthew G. Knepley   if (sfProcess) {
436b0a623aaSMatthew G. Knepley     ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr);
437b0a623aaSMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) *sfProcess, "Two-Sided Process SF");CHKERRQ(ierr);
438b0a623aaSMatthew G. Knepley     ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr);
439*9852e123SBarry Smith     ierr = PetscSFSetGraph(*sfProcess, size, numNeighbors, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
440b0a623aaSMatthew G. Knepley   }
441b0a623aaSMatthew G. Knepley   PetscFunctionReturn(0);
442b0a623aaSMatthew G. Knepley }
443b0a623aaSMatthew G. Knepley 
444b0a623aaSMatthew G. Knepley /*@
445b0a623aaSMatthew G. Knepley   DMPlexDistributeOwnership - Compute owner information for shared points. This basically gets two-sided for an SF.
446b0a623aaSMatthew G. Knepley 
447b0a623aaSMatthew G. Knepley   Collective on DM
448b0a623aaSMatthew G. Knepley 
449b0a623aaSMatthew G. Knepley   Input Parameter:
450b0a623aaSMatthew G. Knepley . dm - The DM
451b0a623aaSMatthew G. Knepley 
452b0a623aaSMatthew G. Knepley   Output Parameters:
453b0a623aaSMatthew G. Knepley + rootSection - The number of leaves for a given root point
454b0a623aaSMatthew G. Knepley . rootrank    - The rank of each edge into the root point
455b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point
456b0a623aaSMatthew G. Knepley - leafrank    - The rank of each process sharing a leaf point
457b0a623aaSMatthew G. Knepley 
458b0a623aaSMatthew G. Knepley   Level: developer
459b0a623aaSMatthew G. Knepley 
460b0a623aaSMatthew G. Knepley .seealso: DMPlexCreateOverlap()
461b0a623aaSMatthew G. Knepley @*/
462b0a623aaSMatthew G. Knepley PetscErrorCode DMPlexDistributeOwnership(DM dm, PetscSection rootSection, IS *rootrank, PetscSection leafSection, IS *leafrank)
463b0a623aaSMatthew G. Knepley {
464b0a623aaSMatthew G. Knepley   MPI_Comm        comm;
465b0a623aaSMatthew G. Knepley   PetscSF         sfPoint;
466b0a623aaSMatthew G. Knepley   const PetscInt *rootdegree;
467b0a623aaSMatthew G. Knepley   PetscInt       *myrank, *remoterank;
468b0a623aaSMatthew G. Knepley   PetscInt        pStart, pEnd, p, nedges;
469b0a623aaSMatthew G. Knepley   PetscMPIInt     rank;
470b0a623aaSMatthew G. Knepley   PetscErrorCode  ierr;
471b0a623aaSMatthew G. Knepley 
472b0a623aaSMatthew G. Knepley   PetscFunctionBegin;
473b0a623aaSMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
474b0a623aaSMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
475b0a623aaSMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
476b0a623aaSMatthew G. Knepley   ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
477b0a623aaSMatthew G. Knepley   /* Compute number of leaves for each root */
478b0a623aaSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) rootSection, "Root Section");CHKERRQ(ierr);
479b0a623aaSMatthew G. Knepley   ierr = PetscSectionSetChart(rootSection, pStart, pEnd);CHKERRQ(ierr);
480b0a623aaSMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(sfPoint, &rootdegree);CHKERRQ(ierr);
481b0a623aaSMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(sfPoint, &rootdegree);CHKERRQ(ierr);
482b0a623aaSMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {ierr = PetscSectionSetDof(rootSection, p, rootdegree[p-pStart]);CHKERRQ(ierr);}
483b0a623aaSMatthew G. Knepley   ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr);
484b0a623aaSMatthew G. Knepley   /* Gather rank of each leaf to root */
485b0a623aaSMatthew G. Knepley   ierr = PetscSectionGetStorageSize(rootSection, &nedges);CHKERRQ(ierr);
486b0a623aaSMatthew G. Knepley   ierr = PetscMalloc1(pEnd-pStart, &myrank);CHKERRQ(ierr);
487b0a623aaSMatthew G. Knepley   ierr = PetscMalloc1(nedges,  &remoterank);CHKERRQ(ierr);
488b0a623aaSMatthew G. Knepley   for (p = 0; p < pEnd-pStart; ++p) myrank[p] = rank;
489b0a623aaSMatthew G. Knepley   ierr = PetscSFGatherBegin(sfPoint, MPIU_INT, myrank, remoterank);CHKERRQ(ierr);
490b0a623aaSMatthew G. Knepley   ierr = PetscSFGatherEnd(sfPoint, MPIU_INT, myrank, remoterank);CHKERRQ(ierr);
491b0a623aaSMatthew G. Knepley   ierr = PetscFree(myrank);CHKERRQ(ierr);
492b0a623aaSMatthew G. Knepley   ierr = ISCreateGeneral(comm, nedges, remoterank, PETSC_OWN_POINTER, rootrank);CHKERRQ(ierr);
493b0a623aaSMatthew G. Knepley   /* Distribute remote ranks to leaves */
494b0a623aaSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) leafSection, "Leaf Section");CHKERRQ(ierr);
495b0a623aaSMatthew G. Knepley   ierr = DMPlexDistributeFieldIS(dm, sfPoint, rootSection, *rootrank, leafSection, leafrank);CHKERRQ(ierr);
496b0a623aaSMatthew G. Knepley   PetscFunctionReturn(0);
497b0a623aaSMatthew G. Knepley }
498b0a623aaSMatthew G. Knepley 
499278397a0SMatthew G. Knepley /*@C
500b0a623aaSMatthew G. Knepley   DMPlexCreateOverlap - Compute owner information for shared points. This basically gets two-sided for an SF.
501b0a623aaSMatthew G. Knepley 
502b0a623aaSMatthew G. Knepley   Collective on DM
503b0a623aaSMatthew G. Knepley 
504b0a623aaSMatthew G. Knepley   Input Parameters:
505b0a623aaSMatthew G. Knepley + dm          - The DM
50624d039d7SMichael Lange . levels      - Number of overlap levels
507b0a623aaSMatthew G. Knepley . rootSection - The number of leaves for a given root point
508b0a623aaSMatthew G. Knepley . rootrank    - The rank of each edge into the root point
509b0a623aaSMatthew G. Knepley . leafSection - The number of processes sharing a given leaf point
510b0a623aaSMatthew G. Knepley - leafrank    - The rank of each process sharing a leaf point
511b0a623aaSMatthew G. Knepley 
512b0a623aaSMatthew G. Knepley   Output Parameters:
513a9f1d5b2SMichael Lange + ovLabel     - DMLabel containing remote overlap contributions as point/rank pairings
514b0a623aaSMatthew G. Knepley 
515b0a623aaSMatthew G. Knepley   Level: developer
516b0a623aaSMatthew G. Knepley 
5171fd9873aSMichael Lange .seealso: DMPlexDistributeOwnership(), DMPlexDistribute()
518b0a623aaSMatthew G. Knepley @*/
519a9f1d5b2SMichael Lange PetscErrorCode DMPlexCreateOverlap(DM dm, PetscInt levels, PetscSection rootSection, IS rootrank, PetscSection leafSection, IS leafrank, DMLabel *ovLabel)
520b0a623aaSMatthew G. Knepley {
521e540f424SMichael Lange   MPI_Comm           comm;
522b0a623aaSMatthew G. Knepley   DMLabel            ovAdjByRank; /* A DMLabel containing all points adjacent to shared points, separated by rank (value in label) */
523b0a623aaSMatthew G. Knepley   PetscSF            sfPoint, sfProc;
524b0a623aaSMatthew G. Knepley   const PetscSFNode *remote;
525b0a623aaSMatthew G. Knepley   const PetscInt    *local;
5261fd9873aSMichael Lange   const PetscInt    *nrank, *rrank;
527b0a623aaSMatthew G. Knepley   PetscInt          *adj = NULL;
5281fd9873aSMichael Lange   PetscInt           pStart, pEnd, p, sStart, sEnd, nleaves, l;
529*9852e123SBarry Smith   PetscMPIInt        rank, size;
53026a7d390SMatthew G. Knepley   PetscBool          useCone, useClosure, flg;
531b0a623aaSMatthew G. Knepley   PetscErrorCode     ierr;
532b0a623aaSMatthew G. Knepley 
533b0a623aaSMatthew G. Knepley   PetscFunctionBegin;
534e540f424SMichael Lange   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
535*9852e123SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
536e540f424SMichael Lange   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
537b0a623aaSMatthew G. Knepley   ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
538b0a623aaSMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
539b0a623aaSMatthew G. Knepley   ierr = PetscSectionGetChart(leafSection, &sStart, &sEnd);CHKERRQ(ierr);
540b0a623aaSMatthew G. Knepley   ierr = PetscSFGetGraph(sfPoint, NULL, &nleaves, &local, &remote);CHKERRQ(ierr);
541b0a623aaSMatthew G. Knepley   ierr = DMLabelCreate("Overlap adjacency", &ovAdjByRank);CHKERRQ(ierr);
542b0a623aaSMatthew G. Knepley   /* Handle leaves: shared with the root point */
543b0a623aaSMatthew G. Knepley   for (l = 0; l < nleaves; ++l) {
544b0a623aaSMatthew G. Knepley     PetscInt adjSize = PETSC_DETERMINE, a;
545b0a623aaSMatthew G. Knepley 
546b0a623aaSMatthew G. Knepley     ierr = DMPlexGetAdjacency(dm, local[l], &adjSize, &adj);CHKERRQ(ierr);
547b0a623aaSMatthew G. Knepley     for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(ovAdjByRank, adj[a], remote[l].rank);CHKERRQ(ierr);}
548b0a623aaSMatthew G. Knepley   }
549b0a623aaSMatthew G. Knepley   ierr = ISGetIndices(rootrank, &rrank);CHKERRQ(ierr);
550b0a623aaSMatthew G. Knepley   ierr = ISGetIndices(leafrank, &nrank);CHKERRQ(ierr);
551b0a623aaSMatthew G. Knepley   /* Handle roots */
552b0a623aaSMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
553b0a623aaSMatthew G. Knepley     PetscInt adjSize = PETSC_DETERMINE, neighbors = 0, noff, n, a;
554b0a623aaSMatthew G. Knepley 
555b0a623aaSMatthew G. Knepley     if ((p >= sStart) && (p < sEnd)) {
556b0a623aaSMatthew G. Knepley       /* Some leaves share a root with other leaves on different processes */
557b0a623aaSMatthew G. Knepley       ierr = PetscSectionGetDof(leafSection, p, &neighbors);CHKERRQ(ierr);
558b0a623aaSMatthew G. Knepley       if (neighbors) {
559b0a623aaSMatthew G. Knepley         ierr = PetscSectionGetOffset(leafSection, p, &noff);CHKERRQ(ierr);
560b0a623aaSMatthew G. Knepley         ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr);
561b0a623aaSMatthew G. Knepley         for (n = 0; n < neighbors; ++n) {
562b0a623aaSMatthew G. Knepley           const PetscInt remoteRank = nrank[noff+n];
563b0a623aaSMatthew G. Knepley 
564b0a623aaSMatthew G. Knepley           if (remoteRank == rank) continue;
565b0a623aaSMatthew G. Knepley           for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(ovAdjByRank, adj[a], remoteRank);CHKERRQ(ierr);}
566b0a623aaSMatthew G. Knepley         }
567b0a623aaSMatthew G. Knepley       }
568b0a623aaSMatthew G. Knepley     }
569b0a623aaSMatthew G. Knepley     /* Roots are shared with leaves */
570b0a623aaSMatthew G. Knepley     ierr = PetscSectionGetDof(rootSection, p, &neighbors);CHKERRQ(ierr);
571b0a623aaSMatthew G. Knepley     if (!neighbors) continue;
572b0a623aaSMatthew G. Knepley     ierr = PetscSectionGetOffset(rootSection, p, &noff);CHKERRQ(ierr);
573b0a623aaSMatthew G. Knepley     ierr = DMPlexGetAdjacency(dm, p, &adjSize, &adj);CHKERRQ(ierr);
574b0a623aaSMatthew G. Knepley     for (n = 0; n < neighbors; ++n) {
575b0a623aaSMatthew G. Knepley       const PetscInt remoteRank = rrank[noff+n];
576b0a623aaSMatthew G. Knepley 
577b0a623aaSMatthew G. Knepley       if (remoteRank == rank) continue;
578b0a623aaSMatthew G. Knepley       for (a = 0; a < adjSize; ++a) {ierr = DMLabelSetValue(ovAdjByRank, adj[a], remoteRank);CHKERRQ(ierr);}
579b0a623aaSMatthew G. Knepley     }
580b0a623aaSMatthew G. Knepley   }
581b0a623aaSMatthew G. Knepley   ierr = PetscFree(adj);CHKERRQ(ierr);
582b0a623aaSMatthew G. Knepley   ierr = ISRestoreIndices(rootrank, &rrank);CHKERRQ(ierr);
583b0a623aaSMatthew G. Knepley   ierr = ISRestoreIndices(leafrank, &nrank);CHKERRQ(ierr);
58424d039d7SMichael Lange   /* Add additional overlap levels */
585be200f8dSMichael Lange   for (l = 1; l < levels; l++) {
586be200f8dSMichael Lange     /* Propagate point donations over SF to capture remote connections */
587be200f8dSMichael Lange     ierr = DMPlexPartitionLabelPropagate(dm, ovAdjByRank);CHKERRQ(ierr);
588be200f8dSMichael Lange     /* Add next level of point donations to the label */
589be200f8dSMichael Lange     ierr = DMPlexPartitionLabelAdjacency(dm, ovAdjByRank);CHKERRQ(ierr);
590be200f8dSMichael Lange   }
59126a7d390SMatthew G. Knepley   /* We require the closure in the overlap */
59226a7d390SMatthew G. Knepley   ierr = DMPlexGetAdjacencyUseCone(dm, &useCone);CHKERRQ(ierr);
59326a7d390SMatthew G. Knepley   ierr = DMPlexGetAdjacencyUseClosure(dm, &useClosure);CHKERRQ(ierr);
59426a7d390SMatthew G. Knepley   if (useCone || !useClosure) {
5955abbe4feSMichael Lange     ierr = DMPlexPartitionLabelClosure(dm, ovAdjByRank);CHKERRQ(ierr);
59626a7d390SMatthew G. Knepley   }
597c5929fdfSBarry Smith   ierr = PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-overlap_view", &flg);CHKERRQ(ierr);
598e540f424SMichael Lange   if (flg) {
599b0a623aaSMatthew G. Knepley     ierr = DMLabelView(ovAdjByRank, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
600b0a623aaSMatthew G. Knepley   }
60171a8c5fcSMichael Lange   /* Make global process SF and invert sender to receiver label */
60271a8c5fcSMichael Lange   {
60371a8c5fcSMichael Lange     /* Build a global process SF */
60471a8c5fcSMichael Lange     PetscSFNode *remoteProc;
605*9852e123SBarry Smith     ierr = PetscMalloc1(size, &remoteProc);CHKERRQ(ierr);
606*9852e123SBarry Smith     for (p = 0; p < size; ++p) {
60771a8c5fcSMichael Lange       remoteProc[p].rank  = p;
60871a8c5fcSMichael Lange       remoteProc[p].index = rank;
60971a8c5fcSMichael Lange     }
61071a8c5fcSMichael Lange     ierr = PetscSFCreate(comm, &sfProc);CHKERRQ(ierr);
61171a8c5fcSMichael Lange     ierr = PetscObjectSetName((PetscObject) sfProc, "Process SF");CHKERRQ(ierr);
612*9852e123SBarry Smith     ierr = PetscSFSetGraph(sfProc, size, size, NULL, PETSC_OWN_POINTER, remoteProc, PETSC_OWN_POINTER);CHKERRQ(ierr);
61371a8c5fcSMichael Lange   }
614a9f1d5b2SMichael Lange   ierr = DMLabelCreate("Overlap label", ovLabel);CHKERRQ(ierr);
615a9f1d5b2SMichael Lange   ierr = DMPlexPartitionLabelInvert(dm, ovAdjByRank, sfProc, *ovLabel);CHKERRQ(ierr);
616a9f1d5b2SMichael Lange   /* Add owned points, except for shared local points */
617a9f1d5b2SMichael Lange   for (p = pStart; p < pEnd; ++p) {ierr = DMLabelSetValue(*ovLabel, p, rank);CHKERRQ(ierr);}
618e540f424SMichael Lange   for (l = 0; l < nleaves; ++l) {
619a9f1d5b2SMichael Lange     ierr = DMLabelClearValue(*ovLabel, local[l], rank);CHKERRQ(ierr);
620a9f1d5b2SMichael Lange     ierr = DMLabelSetValue(*ovLabel, remote[l].index, remote[l].rank);CHKERRQ(ierr);
621e540f424SMichael Lange   }
622e540f424SMichael Lange   /* Clean up */
6231fd9873aSMichael Lange   ierr = DMLabelDestroy(&ovAdjByRank);CHKERRQ(ierr);
624b0a623aaSMatthew G. Knepley   ierr = PetscSFDestroy(&sfProc);CHKERRQ(ierr);
625b0a623aaSMatthew G. Knepley   PetscFunctionReturn(0);
626b0a623aaSMatthew G. Knepley }
62770034214SMatthew G. Knepley 
62846f9b1c3SMichael Lange PetscErrorCode DMPlexCreateOverlapMigrationSF(DM dm, PetscSF overlapSF, PetscSF *migrationSF)
62946f9b1c3SMichael Lange {
63046f9b1c3SMichael Lange   MPI_Comm           comm;
631*9852e123SBarry Smith   PetscMPIInt        rank, size;
63246f9b1c3SMichael Lange   PetscInt           d, dim, p, pStart, pEnd, nroots, nleaves, newLeaves, point, numSharedPoints;
63346f9b1c3SMichael Lange   PetscInt          *pointDepths, *remoteDepths, *ilocal;
63446f9b1c3SMichael Lange   PetscInt          *depthRecv, *depthShift, *depthIdx;
63546f9b1c3SMichael Lange   PetscSFNode       *iremote;
63646f9b1c3SMichael Lange   PetscSF            pointSF;
63746f9b1c3SMichael Lange   const PetscInt    *sharedLocal;
63846f9b1c3SMichael Lange   const PetscSFNode *overlapRemote, *sharedRemote;
63946f9b1c3SMichael Lange   PetscErrorCode     ierr;
64046f9b1c3SMichael Lange 
64146f9b1c3SMichael Lange   PetscFunctionBegin;
64246f9b1c3SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64346f9b1c3SMichael Lange   ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
64446f9b1c3SMichael Lange   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
645*9852e123SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
64646f9b1c3SMichael Lange   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
64746f9b1c3SMichael Lange 
64846f9b1c3SMichael Lange   /* Before building the migration SF we need to know the new stratum offsets */
64946f9b1c3SMichael Lange   ierr = PetscSFGetGraph(overlapSF, &nroots, &nleaves, NULL, &overlapRemote);CHKERRQ(ierr);
65046f9b1c3SMichael Lange   ierr = PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths);CHKERRQ(ierr);
65146f9b1c3SMichael Lange   for (d=0; d<dim+1; d++) {
65246f9b1c3SMichael Lange     ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
65346f9b1c3SMichael Lange     for (p=pStart; p<pEnd; p++) pointDepths[p] = d;
65446f9b1c3SMichael Lange   }
65546f9b1c3SMichael Lange   for (p=0; p<nleaves; p++) remoteDepths[p] = -1;
65646f9b1c3SMichael Lange   ierr = PetscSFBcastBegin(overlapSF, MPIU_INT, pointDepths, remoteDepths);CHKERRQ(ierr);
65746f9b1c3SMichael Lange   ierr = PetscSFBcastEnd(overlapSF, MPIU_INT, pointDepths, remoteDepths);CHKERRQ(ierr);
65846f9b1c3SMichael Lange 
65946f9b1c3SMichael Lange   /* Count recevied points in each stratum and compute the internal strata shift */
66046f9b1c3SMichael Lange   ierr = PetscMalloc3(dim+1, &depthRecv, dim+1, &depthShift, dim+1, &depthIdx);CHKERRQ(ierr);
66146f9b1c3SMichael Lange   for (d=0; d<dim+1; d++) depthRecv[d]=0;
66246f9b1c3SMichael Lange   for (p=0; p<nleaves; p++) depthRecv[remoteDepths[p]]++;
66346f9b1c3SMichael Lange   depthShift[dim] = 0;
66446f9b1c3SMichael Lange   for (d=0; d<dim; d++) depthShift[d] = depthRecv[dim];
66546f9b1c3SMichael Lange   for (d=1; d<dim; d++) depthShift[d] += depthRecv[0];
66646f9b1c3SMichael Lange   for (d=dim-2; d>0; d--) depthShift[d] += depthRecv[d+1];
66746f9b1c3SMichael Lange   for (d=0; d<dim+1; d++) {
66846f9b1c3SMichael Lange     ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
66946f9b1c3SMichael Lange     depthIdx[d] = pStart + depthShift[d];
67046f9b1c3SMichael Lange   }
67146f9b1c3SMichael Lange 
67246f9b1c3SMichael Lange   /* Form the overlap SF build an SF that describes the full overlap migration SF */
67346f9b1c3SMichael Lange   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
67446f9b1c3SMichael Lange   newLeaves = pEnd - pStart + nleaves;
67509b7985cSMatthew G. Knepley   ierr = PetscMalloc1(newLeaves, &ilocal);CHKERRQ(ierr);
67609b7985cSMatthew G. Knepley   ierr = PetscMalloc1(newLeaves, &iremote);CHKERRQ(ierr);
67746f9b1c3SMichael Lange   /* First map local points to themselves */
67846f9b1c3SMichael Lange   for (d=0; d<dim+1; d++) {
67946f9b1c3SMichael Lange     ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
68046f9b1c3SMichael Lange     for (p=pStart; p<pEnd; p++) {
68146f9b1c3SMichael Lange       point = p + depthShift[d];
68246f9b1c3SMichael Lange       ilocal[point] = point;
68346f9b1c3SMichael Lange       iremote[point].index = p;
68446f9b1c3SMichael Lange       iremote[point].rank = rank;
68546f9b1c3SMichael Lange       depthIdx[d]++;
68646f9b1c3SMichael Lange     }
68746f9b1c3SMichael Lange   }
68846f9b1c3SMichael Lange 
68946f9b1c3SMichael Lange   /* Add in the remote roots for currently shared points */
69046f9b1c3SMichael Lange   ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr);
69146f9b1c3SMichael Lange   ierr = PetscSFGetGraph(pointSF, NULL, &numSharedPoints, &sharedLocal, &sharedRemote);CHKERRQ(ierr);
69246f9b1c3SMichael Lange   for (d=0; d<dim+1; d++) {
69346f9b1c3SMichael Lange     ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
69446f9b1c3SMichael Lange     for (p=0; p<numSharedPoints; p++) {
69546f9b1c3SMichael Lange       if (pStart <= sharedLocal[p] && sharedLocal[p] < pEnd) {
69646f9b1c3SMichael Lange         point = sharedLocal[p] + depthShift[d];
69746f9b1c3SMichael Lange         iremote[point].index = sharedRemote[p].index;
69846f9b1c3SMichael Lange         iremote[point].rank = sharedRemote[p].rank;
69946f9b1c3SMichael Lange       }
70046f9b1c3SMichael Lange     }
70146f9b1c3SMichael Lange   }
70246f9b1c3SMichael Lange 
70346f9b1c3SMichael Lange   /* Now add the incoming overlap points */
70446f9b1c3SMichael Lange   for (p=0; p<nleaves; p++) {
70546f9b1c3SMichael Lange     point = depthIdx[remoteDepths[p]];
70646f9b1c3SMichael Lange     ilocal[point] = point;
70746f9b1c3SMichael Lange     iremote[point].index = overlapRemote[p].index;
70846f9b1c3SMichael Lange     iremote[point].rank = overlapRemote[p].rank;
70946f9b1c3SMichael Lange     depthIdx[remoteDepths[p]]++;
71046f9b1c3SMichael Lange   }
71115fff7beSMatthew G. Knepley   ierr = PetscFree2(pointDepths,remoteDepths);CHKERRQ(ierr);
71246f9b1c3SMichael Lange 
71346f9b1c3SMichael Lange   ierr = PetscSFCreate(comm, migrationSF);CHKERRQ(ierr);
71446f9b1c3SMichael Lange   ierr = PetscObjectSetName((PetscObject) *migrationSF, "Overlap Migration SF");CHKERRQ(ierr);
71546f9b1c3SMichael Lange   ierr = PetscSFSetFromOptions(*migrationSF);CHKERRQ(ierr);
71646f9b1c3SMichael Lange   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
71746f9b1c3SMichael Lange   ierr = PetscSFSetGraph(*migrationSF, pEnd-pStart, newLeaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER);CHKERRQ(ierr);
71846f9b1c3SMichael Lange 
71946f9b1c3SMichael Lange   ierr = PetscFree3(depthRecv, depthShift, depthIdx);CHKERRQ(ierr);
72070034214SMatthew G. Knepley   PetscFunctionReturn(0);
72170034214SMatthew G. Knepley }
72270034214SMatthew G. Knepley 
723a9f1d5b2SMichael Lange /*@
724f0e73a3dSToby Isaac   DMPlexStratifyMigrationSF - Rearrange the leaves of a migration sf for stratification.
725a9f1d5b2SMichael Lange 
726a9f1d5b2SMichael Lange   Input Parameter:
727a9f1d5b2SMichael Lange + dm          - The DM
728a9f1d5b2SMichael Lange - sf          - A star forest with non-ordered leaves, usually defining a DM point migration
729a9f1d5b2SMichael Lange 
730a9f1d5b2SMichael Lange   Output Parameter:
731a9f1d5b2SMichael Lange . migrationSF - A star forest with added leaf indirection that ensures the resulting DM is stratified
732a9f1d5b2SMichael Lange 
733a9f1d5b2SMichael Lange   Level: developer
734a9f1d5b2SMichael Lange 
735a9f1d5b2SMichael Lange .seealso: DMPlexPartitionLabelCreateSF(), DMPlexDistribute(), DMPlexDistributeOverlap()
736a9f1d5b2SMichael Lange @*/
737a9f1d5b2SMichael Lange PetscErrorCode DMPlexStratifyMigrationSF(DM dm, PetscSF sf, PetscSF *migrationSF)
738a9f1d5b2SMichael Lange {
739a9f1d5b2SMichael Lange   MPI_Comm           comm;
740*9852e123SBarry Smith   PetscMPIInt        rank, size;
7417fab53ddSMatthew G. Knepley   PetscInt           d, ldepth, depth, p, pStart, pEnd, nroots, nleaves;
742a9f1d5b2SMichael Lange   PetscInt          *pointDepths, *remoteDepths, *ilocal;
743a9f1d5b2SMichael Lange   PetscInt          *depthRecv, *depthShift, *depthIdx;
744f0e73a3dSToby Isaac   PetscInt           hybEnd[4];
745a9f1d5b2SMichael Lange   const PetscSFNode *iremote;
746a9f1d5b2SMichael Lange   PetscErrorCode     ierr;
747a9f1d5b2SMichael Lange 
748a9f1d5b2SMichael Lange   PetscFunctionBegin;
749a9f1d5b2SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
750a9f1d5b2SMichael Lange   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
751a9f1d5b2SMichael Lange   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
752*9852e123SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
7537fab53ddSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &ldepth);CHKERRQ(ierr);
754b2566f29SBarry Smith   ierr = MPIU_Allreduce(&ldepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr);
7557fab53ddSMatthew G. Knepley   if ((ldepth >= 0) && (depth != ldepth)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %d != %d", ldepth, depth);
756a9f1d5b2SMichael Lange 
757a9f1d5b2SMichael Lange   /* Before building the migration SF we need to know the new stratum offsets */
758a9f1d5b2SMichael Lange   ierr = PetscSFGetGraph(sf, &nroots, &nleaves, NULL, &iremote);CHKERRQ(ierr);
759a9f1d5b2SMichael Lange   ierr = PetscMalloc2(nroots, &pointDepths, nleaves, &remoteDepths);CHKERRQ(ierr);
760f0e73a3dSToby Isaac   ierr = DMPlexGetHybridBounds(dm,&hybEnd[depth],&hybEnd[depth-1],&hybEnd[1],&hybEnd[0]);CHKERRQ(ierr);
7617fab53ddSMatthew G. Knepley   for (d = 0; d < depth+1; ++d) {
762a9f1d5b2SMichael Lange     ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
763f0e73a3dSToby Isaac     for (p = pStart; p < pEnd; ++p) {
764f0e73a3dSToby Isaac       if (hybEnd[d] >= 0 && p >= hybEnd[d]) { /* put in a separate value for hybrid points */
765f0e73a3dSToby Isaac         pointDepths[p] = 2 * d;
766f0e73a3dSToby Isaac       } else {
767f0e73a3dSToby Isaac         pointDepths[p] = 2 * d + 1;
768f0e73a3dSToby Isaac       }
769f0e73a3dSToby Isaac     }
770a9f1d5b2SMichael Lange   }
7717fab53ddSMatthew G. Knepley   for (p = 0; p < nleaves; ++p) remoteDepths[p] = -1;
772a9f1d5b2SMichael Lange   ierr = PetscSFBcastBegin(sf, MPIU_INT, pointDepths, remoteDepths);CHKERRQ(ierr);
773a9f1d5b2SMichael Lange   ierr = PetscSFBcastEnd(sf, MPIU_INT, pointDepths, remoteDepths);CHKERRQ(ierr);
774a9f1d5b2SMichael Lange   /* Count recevied points in each stratum and compute the internal strata shift */
775f0e73a3dSToby Isaac   ierr = PetscMalloc3(2*(depth+1), &depthRecv, 2*(depth+1), &depthShift, 2*(depth+1), &depthIdx);CHKERRQ(ierr);
776f0e73a3dSToby Isaac   for (d = 0; d < 2*(depth+1); ++d) depthRecv[d] = 0;
7777fab53ddSMatthew G. Knepley   for (p = 0; p < nleaves; ++p) depthRecv[remoteDepths[p]]++;
778f0e73a3dSToby Isaac   depthShift[2*depth+1] = 0;
779f0e73a3dSToby Isaac   for (d = 0; d < 2*depth+1; ++d) depthShift[d] = depthRecv[2 * depth + 1];
780f0e73a3dSToby Isaac   for (d = 0; d < 2*depth; ++d) depthShift[d] += depthRecv[2 * depth];
781f0e73a3dSToby Isaac   depthShift[0] += depthRecv[1];
782f0e73a3dSToby Isaac   for (d = 2; d < 2*depth; ++d) depthShift[d] += depthRecv[1];
783f0e73a3dSToby Isaac   for (d = 2; d < 2*depth; ++d) depthShift[d] += depthRecv[0];
784f0e73a3dSToby Isaac   for (d = 2 * depth-1; d > 2; --d) {
785f0e73a3dSToby Isaac     PetscInt e;
786f0e73a3dSToby Isaac 
787f0e73a3dSToby Isaac     for (e = d -1; e > 1; --e) depthShift[e] += depthRecv[d];
788f0e73a3dSToby Isaac   }
789f0e73a3dSToby Isaac   for (d = 0; d < 2*(depth+1); ++d) {depthIdx[d] = 0;}
790a9f1d5b2SMichael Lange   /* Derive a new local permutation based on stratified indices */
791a9f1d5b2SMichael Lange   ierr = PetscMalloc1(nleaves, &ilocal);CHKERRQ(ierr);
7927fab53ddSMatthew G. Knepley   for (p = 0; p < nleaves; ++p) {
7937fab53ddSMatthew G. Knepley     const PetscInt dep = remoteDepths[p];
7947fab53ddSMatthew G. Knepley 
7957fab53ddSMatthew G. Knepley     ilocal[p] = depthShift[dep] + depthIdx[dep];
7967fab53ddSMatthew G. Knepley     depthIdx[dep]++;
797a9f1d5b2SMichael Lange   }
798a9f1d5b2SMichael Lange   ierr = PetscSFCreate(comm, migrationSF);CHKERRQ(ierr);
799a9f1d5b2SMichael Lange   ierr = PetscObjectSetName((PetscObject) *migrationSF, "Migration SF");CHKERRQ(ierr);
800a9f1d5b2SMichael Lange   ierr = PetscSFSetGraph(*migrationSF, nroots, nleaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_COPY_VALUES);CHKERRQ(ierr);
801a9f1d5b2SMichael Lange   ierr = PetscFree2(pointDepths,remoteDepths);CHKERRQ(ierr);
802a9f1d5b2SMichael Lange   ierr = PetscFree3(depthRecv, depthShift, depthIdx);CHKERRQ(ierr);
803a9f1d5b2SMichael Lange   PetscFunctionReturn(0);
804a9f1d5b2SMichael Lange }
805a9f1d5b2SMichael Lange 
80670034214SMatthew G. Knepley /*@
80770034214SMatthew G. Knepley   DMPlexDistributeField - Distribute field data to match a given PetscSF, usually the SF from mesh distribution
80870034214SMatthew G. Knepley 
80970034214SMatthew G. Knepley   Collective on DM
81070034214SMatthew G. Knepley 
81170034214SMatthew G. Knepley   Input Parameters:
81270034214SMatthew G. Knepley + dm - The DMPlex object
81370034214SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern
81470034214SMatthew G. Knepley . originalSection - The PetscSection for existing data layout
81570034214SMatthew G. Knepley - originalVec - The existing data
81670034214SMatthew G. Knepley 
81770034214SMatthew G. Knepley   Output Parameters:
81870034214SMatthew G. Knepley + newSection - The PetscSF describing the new data layout
81970034214SMatthew G. Knepley - newVec - The new data
82070034214SMatthew G. Knepley 
82170034214SMatthew G. Knepley   Level: developer
82270034214SMatthew G. Knepley 
82370034214SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeFieldIS(), DMPlexDistributeData()
82470034214SMatthew G. Knepley @*/
82570034214SMatthew G. Knepley PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec)
82670034214SMatthew G. Knepley {
82770034214SMatthew G. Knepley   PetscSF        fieldSF;
82870034214SMatthew G. Knepley   PetscInt      *remoteOffsets, fieldSize;
82970034214SMatthew G. Knepley   PetscScalar   *originalValues, *newValues;
83070034214SMatthew G. Knepley   PetscErrorCode ierr;
83170034214SMatthew G. Knepley 
83270034214SMatthew G. Knepley   PetscFunctionBegin;
83370034214SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_DistributeField,dm,0,0,0);CHKERRQ(ierr);
83470034214SMatthew G. Knepley   ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr);
83570034214SMatthew G. Knepley 
83670034214SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr);
83770034214SMatthew G. Knepley   ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr);
83870034214SMatthew G. Knepley   ierr = VecSetType(newVec,dm->vectype);CHKERRQ(ierr);
83970034214SMatthew G. Knepley 
84070034214SMatthew G. Knepley   ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr);
84170034214SMatthew G. Knepley   ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr);
84270034214SMatthew G. Knepley   ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr);
8438a713f3bSLawrence Mitchell   ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
84470034214SMatthew G. Knepley   ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr);
84570034214SMatthew G. Knepley   ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr);
84670034214SMatthew G. Knepley   ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr);
84770034214SMatthew G. Knepley   ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr);
84870034214SMatthew G. Knepley   ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr);
84970034214SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_DistributeField,dm,0,0,0);CHKERRQ(ierr);
85070034214SMatthew G. Knepley   PetscFunctionReturn(0);
85170034214SMatthew G. Knepley }
85270034214SMatthew G. Knepley 
85370034214SMatthew G. Knepley /*@
85470034214SMatthew G. Knepley   DMPlexDistributeFieldIS - Distribute field data to match a given PetscSF, usually the SF from mesh distribution
85570034214SMatthew G. Knepley 
85670034214SMatthew G. Knepley   Collective on DM
85770034214SMatthew G. Knepley 
85870034214SMatthew G. Knepley   Input Parameters:
85970034214SMatthew G. Knepley + dm - The DMPlex object
86070034214SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern
86170034214SMatthew G. Knepley . originalSection - The PetscSection for existing data layout
86270034214SMatthew G. Knepley - originalIS - The existing data
86370034214SMatthew G. Knepley 
86470034214SMatthew G. Knepley   Output Parameters:
86570034214SMatthew G. Knepley + newSection - The PetscSF describing the new data layout
86670034214SMatthew G. Knepley - newIS - The new data
86770034214SMatthew G. Knepley 
86870034214SMatthew G. Knepley   Level: developer
86970034214SMatthew G. Knepley 
87070034214SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField(), DMPlexDistributeData()
87170034214SMatthew G. Knepley @*/
87270034214SMatthew G. Knepley PetscErrorCode DMPlexDistributeFieldIS(DM dm, PetscSF pointSF, PetscSection originalSection, IS originalIS, PetscSection newSection, IS *newIS)
87370034214SMatthew G. Knepley {
87470034214SMatthew G. Knepley   PetscSF         fieldSF;
87570034214SMatthew G. Knepley   PetscInt       *newValues, *remoteOffsets, fieldSize;
87670034214SMatthew G. Knepley   const PetscInt *originalValues;
87770034214SMatthew G. Knepley   PetscErrorCode  ierr;
87870034214SMatthew G. Knepley 
87970034214SMatthew G. Knepley   PetscFunctionBegin;
88070034214SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_DistributeField,dm,0,0,0);CHKERRQ(ierr);
88170034214SMatthew G. Knepley   ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr);
88270034214SMatthew G. Knepley 
88370034214SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr);
884854ce69bSBarry Smith   ierr = PetscMalloc1(fieldSize, &newValues);CHKERRQ(ierr);
88570034214SMatthew G. Knepley 
88670034214SMatthew G. Knepley   ierr = ISGetIndices(originalIS, &originalValues);CHKERRQ(ierr);
88770034214SMatthew G. Knepley   ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr);
8888a713f3bSLawrence Mitchell   ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
889aaf8c182SMatthew G. Knepley   ierr = PetscSFBcastBegin(fieldSF, MPIU_INT, (PetscInt *) originalValues, newValues);CHKERRQ(ierr);
890aaf8c182SMatthew G. Knepley   ierr = PetscSFBcastEnd(fieldSF, MPIU_INT, (PetscInt *) originalValues, newValues);CHKERRQ(ierr);
89170034214SMatthew G. Knepley   ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr);
89270034214SMatthew G. Knepley   ierr = ISRestoreIndices(originalIS, &originalValues);CHKERRQ(ierr);
89370034214SMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject) pointSF), fieldSize, newValues, PETSC_OWN_POINTER, newIS);CHKERRQ(ierr);
89470034214SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_DistributeField,dm,0,0,0);CHKERRQ(ierr);
89570034214SMatthew G. Knepley   PetscFunctionReturn(0);
89670034214SMatthew G. Knepley }
89770034214SMatthew G. Knepley 
89870034214SMatthew G. Knepley /*@
89970034214SMatthew G. Knepley   DMPlexDistributeData - Distribute field data to match a given PetscSF, usually the SF from mesh distribution
90070034214SMatthew G. Knepley 
90170034214SMatthew G. Knepley   Collective on DM
90270034214SMatthew G. Knepley 
90370034214SMatthew G. Knepley   Input Parameters:
90470034214SMatthew G. Knepley + dm - The DMPlex object
90570034214SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern
90670034214SMatthew G. Knepley . originalSection - The PetscSection for existing data layout
90770034214SMatthew G. Knepley . datatype - The type of data
90870034214SMatthew G. Knepley - originalData - The existing data
90970034214SMatthew G. Knepley 
91070034214SMatthew G. Knepley   Output Parameters:
91170034214SMatthew G. Knepley + newSection - The PetscSection describing the new data layout
91270034214SMatthew G. Knepley - newData - The new data
91370034214SMatthew G. Knepley 
91470034214SMatthew G. Knepley   Level: developer
91570034214SMatthew G. Knepley 
91670034214SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField()
91770034214SMatthew G. Knepley @*/
91870034214SMatthew G. Knepley PetscErrorCode DMPlexDistributeData(DM dm, PetscSF pointSF, PetscSection originalSection, MPI_Datatype datatype, void *originalData, PetscSection newSection, void **newData)
91970034214SMatthew G. Knepley {
92070034214SMatthew G. Knepley   PetscSF        fieldSF;
92170034214SMatthew G. Knepley   PetscInt      *remoteOffsets, fieldSize;
92270034214SMatthew G. Knepley   PetscMPIInt    dataSize;
92370034214SMatthew G. Knepley   PetscErrorCode ierr;
92470034214SMatthew G. Knepley 
92570034214SMatthew G. Knepley   PetscFunctionBegin;
92670034214SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_DistributeData,dm,0,0,0);CHKERRQ(ierr);
92770034214SMatthew G. Knepley   ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr);
92870034214SMatthew G. Knepley 
92970034214SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr);
93070034214SMatthew G. Knepley   ierr = MPI_Type_size(datatype, &dataSize);CHKERRQ(ierr);
93170034214SMatthew G. Knepley   ierr = PetscMalloc(fieldSize * dataSize, newData);CHKERRQ(ierr);
93270034214SMatthew G. Knepley 
93370034214SMatthew G. Knepley   ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr);
9348a713f3bSLawrence Mitchell   ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
93570034214SMatthew G. Knepley   ierr = PetscSFBcastBegin(fieldSF, datatype, originalData, *newData);CHKERRQ(ierr);
93670034214SMatthew G. Knepley   ierr = PetscSFBcastEnd(fieldSF, datatype, originalData, *newData);CHKERRQ(ierr);
93770034214SMatthew G. Knepley   ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr);
93870034214SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_DistributeData,dm,0,0,0);CHKERRQ(ierr);
93970034214SMatthew G. Knepley   PetscFunctionReturn(0);
94070034214SMatthew G. Knepley }
94170034214SMatthew G. Knepley 
942ac04eaf7SToby Isaac PetscErrorCode DMPlexDistributeCones(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel)
943cc71bff1SMichael Lange {
944f5bf2dbfSMichael Lange   DM_Plex               *mesh  = (DM_Plex*) dm->data;
945cc71bff1SMichael Lange   DM_Plex               *pmesh = (DM_Plex*) (dmParallel)->data;
946cc71bff1SMichael Lange   MPI_Comm               comm;
947cc71bff1SMichael Lange   PetscSF                coneSF;
948cc71bff1SMichael Lange   PetscSection           originalConeSection, newConeSection;
949ac04eaf7SToby Isaac   PetscInt              *remoteOffsets, *cones, *globCones, *newCones, newConesSize;
950cc71bff1SMichael Lange   PetscBool              flg;
951cc71bff1SMichael Lange   PetscErrorCode         ierr;
952cc71bff1SMichael Lange 
953cc71bff1SMichael Lange   PetscFunctionBegin;
954cc71bff1SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
955cc71bff1SMichael Lange   PetscValidPointer(dmParallel,4);
956cc71bff1SMichael Lange   ierr = PetscLogEventBegin(DMPLEX_DistributeCones,dm,0,0,0);CHKERRQ(ierr);
957cc71bff1SMichael Lange 
958cc71bff1SMichael Lange   /* Distribute cone section */
959cc71bff1SMichael Lange   ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
960cc71bff1SMichael Lange   ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr);
961cc71bff1SMichael Lange   ierr = DMPlexGetConeSection(dmParallel, &newConeSection);CHKERRQ(ierr);
962cc71bff1SMichael Lange   ierr = PetscSFDistributeSection(migrationSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr);
963cc71bff1SMichael Lange   ierr = DMSetUp(dmParallel);CHKERRQ(ierr);
964cc71bff1SMichael Lange   {
965cc71bff1SMichael Lange     PetscInt pStart, pEnd, p;
966cc71bff1SMichael Lange 
967cc71bff1SMichael Lange     ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr);
968cc71bff1SMichael Lange     for (p = pStart; p < pEnd; ++p) {
969cc71bff1SMichael Lange       PetscInt coneSize;
970cc71bff1SMichael Lange       ierr               = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr);
971cc71bff1SMichael Lange       pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize);
972cc71bff1SMichael Lange     }
973cc71bff1SMichael Lange   }
974cc71bff1SMichael Lange   /* Communicate and renumber cones */
975cc71bff1SMichael Lange   ierr = PetscSFCreateSectionSF(migrationSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr);
9768a713f3bSLawrence Mitchell   ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
977cc71bff1SMichael Lange   ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr);
978ac04eaf7SToby Isaac   if (original) {
979ac04eaf7SToby Isaac     PetscInt numCones;
980ac04eaf7SToby Isaac 
981ac04eaf7SToby Isaac     ierr = PetscSectionGetStorageSize(originalConeSection,&numCones);CHKERRQ(ierr); ierr = PetscMalloc1(numCones,&globCones);CHKERRQ(ierr);
982ac04eaf7SToby Isaac     ierr = ISLocalToGlobalMappingApplyBlock(original, numCones, cones, globCones);CHKERRQ(ierr);
983ac04eaf7SToby Isaac   }
984ac04eaf7SToby Isaac   else {
985ac04eaf7SToby Isaac     globCones = cones;
986ac04eaf7SToby Isaac   }
987cc71bff1SMichael Lange   ierr = DMPlexGetCones(dmParallel, &newCones);CHKERRQ(ierr);
988ac04eaf7SToby Isaac   ierr = PetscSFBcastBegin(coneSF, MPIU_INT, globCones, newCones);CHKERRQ(ierr);
989ac04eaf7SToby Isaac   ierr = PetscSFBcastEnd(coneSF, MPIU_INT, globCones, newCones);CHKERRQ(ierr);
990ac04eaf7SToby Isaac   if (original) {
991ac04eaf7SToby Isaac     ierr = PetscFree(globCones);CHKERRQ(ierr);
992ac04eaf7SToby Isaac   }
993cc71bff1SMichael Lange   ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr);
994cc71bff1SMichael Lange   ierr = ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr);
9953533c52bSMatthew G. Knepley #if PETSC_USE_DEBUG
9963533c52bSMatthew G. Knepley   {
9973533c52bSMatthew G. Knepley     PetscInt  p;
9983533c52bSMatthew G. Knepley     PetscBool valid = PETSC_TRUE;
9993533c52bSMatthew G. Knepley     for (p = 0; p < newConesSize; ++p) {
10003533c52bSMatthew G. Knepley       if (newCones[p] < 0) {valid = PETSC_FALSE; ierr = PetscPrintf(PETSC_COMM_SELF, "Point %d not in overlap SF\n", p);CHKERRQ(ierr);}
10013533c52bSMatthew G. Knepley     }
10023533c52bSMatthew G. Knepley     if (!valid) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map");
10033533c52bSMatthew G. Knepley   }
10043533c52bSMatthew G. Knepley #endif
1005c5929fdfSBarry Smith   ierr = PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr);
1006cc71bff1SMichael Lange   if (flg) {
1007cc71bff1SMichael Lange     ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr);
1008cc71bff1SMichael Lange     ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
1009cc71bff1SMichael Lange     ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr);
1010cc71bff1SMichael Lange     ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
1011cc71bff1SMichael Lange     ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr);
1012cc71bff1SMichael Lange   }
1013cc71bff1SMichael Lange   ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr);
1014cc71bff1SMichael Lange   ierr = DMPlexGetConeOrientations(dmParallel, &newCones);CHKERRQ(ierr);
1015cc71bff1SMichael Lange   ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
1016cc71bff1SMichael Lange   ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
1017cc71bff1SMichael Lange   ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr);
1018cc71bff1SMichael Lange   ierr = PetscLogEventEnd(DMPLEX_DistributeCones,dm,0,0,0);CHKERRQ(ierr);
1019cc71bff1SMichael Lange   /* Create supports and stratify sieve */
1020cc71bff1SMichael Lange   {
1021cc71bff1SMichael Lange     PetscInt pStart, pEnd;
1022cc71bff1SMichael Lange 
1023cc71bff1SMichael Lange     ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
1024cc71bff1SMichael Lange     ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr);
1025cc71bff1SMichael Lange   }
1026cc71bff1SMichael Lange   ierr = DMPlexSymmetrize(dmParallel);CHKERRQ(ierr);
1027cc71bff1SMichael Lange   ierr = DMPlexStratify(dmParallel);CHKERRQ(ierr);
1028f5bf2dbfSMichael Lange   pmesh->useCone    = mesh->useCone;
1029f5bf2dbfSMichael Lange   pmesh->useClosure = mesh->useClosure;
1030cc71bff1SMichael Lange   PetscFunctionReturn(0);
1031cc71bff1SMichael Lange }
1032cc71bff1SMichael Lange 
10330df0e737SMichael Lange PetscErrorCode DMPlexDistributeCoordinates(DM dm, PetscSF migrationSF, DM dmParallel)
10340df0e737SMichael Lange {
10350df0e737SMichael Lange   MPI_Comm         comm;
10360df0e737SMichael Lange   PetscSection     originalCoordSection, newCoordSection;
10370df0e737SMichael Lange   Vec              originalCoordinates, newCoordinates;
10380df0e737SMichael Lange   PetscInt         bs;
10390df0e737SMichael Lange   const char      *name;
10400df0e737SMichael Lange   const PetscReal *maxCell, *L;
10415dc8c3f7SMatthew G. Knepley   const DMBoundaryType *bd;
10420df0e737SMichael Lange   PetscErrorCode   ierr;
10430df0e737SMichael Lange 
10440df0e737SMichael Lange   PetscFunctionBegin;
10450df0e737SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10460df0e737SMichael Lange   PetscValidPointer(dmParallel, 3);
10470df0e737SMichael Lange 
10480df0e737SMichael Lange   ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
10490df0e737SMichael Lange   ierr = DMGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr);
10500df0e737SMichael Lange   ierr = DMGetCoordinateSection(dmParallel, &newCoordSection);CHKERRQ(ierr);
10510df0e737SMichael Lange   ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr);
10520df0e737SMichael Lange   if (originalCoordinates) {
10538b9ced59SLisandro Dalcin     ierr = VecCreate(PETSC_COMM_SELF, &newCoordinates);CHKERRQ(ierr);
10540df0e737SMichael Lange     ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr);
10550df0e737SMichael Lange     ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr);
10560df0e737SMichael Lange 
10570df0e737SMichael Lange     ierr = DMPlexDistributeField(dm, migrationSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr);
10580df0e737SMichael Lange     ierr = DMSetCoordinatesLocal(dmParallel, newCoordinates);CHKERRQ(ierr);
10590df0e737SMichael Lange     ierr = VecGetBlockSize(originalCoordinates, &bs);CHKERRQ(ierr);
10600df0e737SMichael Lange     ierr = VecSetBlockSize(newCoordinates, bs);CHKERRQ(ierr);
10610df0e737SMichael Lange     ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr);
10620df0e737SMichael Lange   }
10635dc8c3f7SMatthew G. Knepley   ierr = DMGetPeriodicity(dm, &maxCell, &L, &bd);CHKERRQ(ierr);
10645dc8c3f7SMatthew G. Knepley   if (L) {ierr = DMSetPeriodicity(dmParallel, maxCell, L, bd);CHKERRQ(ierr);}
10650df0e737SMichael Lange   PetscFunctionReturn(0);
10660df0e737SMichael Lange }
10670df0e737SMichael Lange 
1068d995df53SMatthew G. Knepley /* Here we are assuming that process 0 always has everything */
10692eb1fa14SMichael Lange PetscErrorCode DMPlexDistributeLabels(DM dm, PetscSF migrationSF, DM dmParallel)
10700df0e737SMichael Lange {
1071df0420ecSMatthew G. Knepley   DM_Plex         *mesh = (DM_Plex*) dm->data;
10720df0e737SMichael Lange   MPI_Comm         comm;
10737980c9d4SMatthew G. Knepley   DMLabel          depthLabel;
10740df0e737SMichael Lange   PetscMPIInt      rank;
10757980c9d4SMatthew G. Knepley   PetscInt         depth, d, numLabels, numLocalLabels, l;
1076df0420ecSMatthew G. Knepley   PetscBool        hasLabels = PETSC_FALSE, lsendDepth, sendDepth;
1077df0420ecSMatthew G. Knepley   PetscObjectState depthState = -1;
10780df0e737SMichael Lange   PetscErrorCode   ierr;
10790df0e737SMichael Lange 
10800df0e737SMichael Lange   PetscFunctionBegin;
10810df0e737SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10822eb1fa14SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 3);
10830df0e737SMichael Lange   ierr = PetscLogEventBegin(DMPLEX_DistributeLabels,dm,0,0,0);CHKERRQ(ierr);
10840df0e737SMichael Lange   ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
10850df0e737SMichael Lange   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
10860df0e737SMichael Lange 
1087df0420ecSMatthew G. Knepley   /* If the user has changed the depth label, communicate it instead */
10887980c9d4SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
10897980c9d4SMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr);
10907980c9d4SMatthew G. Knepley   if (depthLabel) {ierr = DMLabelGetState(depthLabel, &depthState);CHKERRQ(ierr);}
1091df0420ecSMatthew G. Knepley   lsendDepth = mesh->depthState != depthState ? PETSC_TRUE : PETSC_FALSE;
1092b2566f29SBarry Smith   ierr = MPIU_Allreduce(&lsendDepth, &sendDepth, 1, MPIU_BOOL, MPI_LOR, comm);CHKERRQ(ierr);
1093df0420ecSMatthew G. Knepley   if (sendDepth) {
10947980c9d4SMatthew G. Knepley     ierr = DMRemoveLabel(dmParallel, "depth", &depthLabel);CHKERRQ(ierr);
10957980c9d4SMatthew G. Knepley     ierr = DMLabelDestroy(&depthLabel);CHKERRQ(ierr);
1096df0420ecSMatthew G. Knepley   }
1097d995df53SMatthew G. Knepley   /* Everyone must have either the same number of labels, or none */
1098c58f1c22SToby Isaac   ierr = DMGetNumLabels(dm, &numLocalLabels);CHKERRQ(ierr);
1099d995df53SMatthew G. Knepley   numLabels = numLocalLabels;
11000df0e737SMichael Lange   ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
1101627847f0SMatthew G. Knepley   if (numLabels == numLocalLabels) hasLabels = PETSC_TRUE;
1102bdd2d751SMichael Lange   for (l = numLabels-1; l >= 0; --l) {
1103bdd2d751SMichael Lange     DMLabel     label = NULL, labelNew = NULL;
11040df0e737SMichael Lange     PetscBool   isdepth;
11050df0e737SMichael Lange 
1106d995df53SMatthew G. Knepley     if (hasLabels) {
1107c58f1c22SToby Isaac       ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr);
11080df0e737SMichael Lange       /* Skip "depth" because it is recreated */
1109bdd2d751SMichael Lange       ierr = PetscStrcmp(label->name, "depth", &isdepth);CHKERRQ(ierr);
1110bdd2d751SMichael Lange     }
11110df0e737SMichael Lange     ierr = MPI_Bcast(&isdepth, 1, MPIU_BOOL, 0, comm);CHKERRQ(ierr);
1112df0420ecSMatthew G. Knepley     if (isdepth && !sendDepth) continue;
1113bdd2d751SMichael Lange     ierr = DMLabelDistribute(label, migrationSF, &labelNew);CHKERRQ(ierr);
11147980c9d4SMatthew G. Knepley     if (isdepth) {
11157980c9d4SMatthew G. Knepley       /* Put in any missing strata which can occur if users are managing the depth label themselves */
11167980c9d4SMatthew G. Knepley       PetscInt gdepth;
11177980c9d4SMatthew G. Knepley 
11187980c9d4SMatthew G. Knepley       ierr = MPIU_Allreduce(&depth, &gdepth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr);
11197980c9d4SMatthew G. Knepley       if ((depth >= 0) && (gdepth != depth)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %d != %d", depth, gdepth);
11207980c9d4SMatthew G. Knepley       for (d = 0; d <= gdepth; ++d) {
11217980c9d4SMatthew G. Knepley         PetscBool has;
11227980c9d4SMatthew G. Knepley 
11237980c9d4SMatthew G. Knepley         ierr = DMLabelHasStratum(labelNew, d, &has);CHKERRQ(ierr);
11247980c9d4SMatthew G. Knepley         if (!has) ierr = DMLabelAddStratum(labelNew, d);CHKERRQ(ierr);
11257980c9d4SMatthew G. Knepley       }
11267980c9d4SMatthew G. Knepley     }
1127c58f1c22SToby Isaac     ierr = DMAddLabel(dmParallel, labelNew);CHKERRQ(ierr);
11280df0e737SMichael Lange   }
11290df0e737SMichael Lange   ierr = PetscLogEventEnd(DMPLEX_DistributeLabels,dm,0,0,0);CHKERRQ(ierr);
11300df0e737SMichael Lange   PetscFunctionReturn(0);
11310df0e737SMichael Lange }
11320df0e737SMichael Lange 
11339734c634SMichael Lange PetscErrorCode DMPlexDistributeSetupHybrid(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping renumbering, DM dmParallel)
11349734c634SMichael Lange {
11359734c634SMichael Lange   DM_Plex        *mesh  = (DM_Plex*) dm->data;
11369734c634SMichael Lange   DM_Plex        *pmesh = (DM_Plex*) (dmParallel)->data;
1137f0e73a3dSToby Isaac   PetscBool      *isHybrid, *isHybridParallel;
1138f0e73a3dSToby Isaac   PetscInt        dim, depth, d;
1139f0e73a3dSToby Isaac   PetscInt        pStart, pEnd, pStartP, pEndP;
11409734c634SMichael Lange   PetscErrorCode  ierr;
11419734c634SMichael Lange 
11429734c634SMichael Lange   PetscFunctionBegin;
11439734c634SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11449734c634SMichael Lange   PetscValidPointer(dmParallel, 4);
11459734c634SMichael Lange 
11469734c634SMichael Lange   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
11479734c634SMichael Lange   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1148f0e73a3dSToby Isaac   ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr);
1149f0e73a3dSToby Isaac   ierr = DMPlexGetChart(dmParallel,&pStartP,&pEndP);CHKERRQ(ierr);
1150f0e73a3dSToby Isaac   ierr = PetscCalloc2(pEnd-pStart,&isHybrid,pEndP-pStartP,&isHybridParallel);CHKERRQ(ierr);
1151f0e73a3dSToby Isaac   for (d = 0; d <= depth; d++) {
1152f0e73a3dSToby Isaac     PetscInt hybridMax = (depth == 1 && d == 1) ? mesh->hybridPointMax[dim] : mesh->hybridPointMax[d];
11539734c634SMichael Lange 
1154f0e73a3dSToby Isaac     if (hybridMax >= 0) {
1155f0e73a3dSToby Isaac       PetscInt sStart, sEnd, p;
11569734c634SMichael Lange 
1157f0e73a3dSToby Isaac       ierr = DMPlexGetDepthStratum(dm,d,&sStart,&sEnd);CHKERRQ(ierr);
1158f0e73a3dSToby Isaac       for (p = hybridMax; p < sEnd; p++) isHybrid[p-pStart] = PETSC_TRUE;
11599734c634SMichael Lange     }
11609734c634SMichael Lange   }
1161f0e73a3dSToby Isaac   ierr = PetscSFBcastBegin(migrationSF,MPIU_BOOL,isHybrid,isHybridParallel);CHKERRQ(ierr);
1162f0e73a3dSToby Isaac   ierr = PetscSFBcastEnd(migrationSF,MPIU_BOOL,isHybrid,isHybridParallel);CHKERRQ(ierr);
1163f0e73a3dSToby Isaac   for (d = 0; d <= dim; d++) pmesh->hybridPointMax[d] = -1;
1164f0e73a3dSToby Isaac   for (d = 0; d <= depth; d++) {
1165f0e73a3dSToby Isaac     PetscInt sStart, sEnd, p, dd;
1166f0e73a3dSToby Isaac 
1167f0e73a3dSToby Isaac     ierr = DMPlexGetDepthStratum(dmParallel,d,&sStart,&sEnd);CHKERRQ(ierr);
1168f0e73a3dSToby Isaac     dd = (depth == 1 && d == 1) ? dim : d;
1169f0e73a3dSToby Isaac     for (p = sStart; p < sEnd; p++) {
1170f0e73a3dSToby Isaac       if (isHybridParallel[p-pStartP]) {
1171f0e73a3dSToby Isaac         pmesh->hybridPointMax[dd] = p;
1172f0e73a3dSToby Isaac         break;
1173f0e73a3dSToby Isaac       }
1174f0e73a3dSToby Isaac     }
1175f0e73a3dSToby Isaac   }
1176f0e73a3dSToby Isaac   ierr = PetscFree2(isHybrid,isHybridParallel);CHKERRQ(ierr);
11779734c634SMichael Lange   PetscFunctionReturn(0);
11789734c634SMichael Lange }
11790df0e737SMichael Lange 
118008633170SToby Isaac PetscErrorCode DMPlexDistributeSetupTree(DM dm, PetscSF migrationSF, ISLocalToGlobalMapping original, ISLocalToGlobalMapping renumbering, DM dmParallel)
1181a6f36705SMichael Lange {
118215078cd4SMichael Lange   DM_Plex        *mesh  = (DM_Plex*) dm->data;
118315078cd4SMichael Lange   DM_Plex        *pmesh = (DM_Plex*) (dmParallel)->data;
1184a6f36705SMichael Lange   MPI_Comm        comm;
1185a6f36705SMichael Lange   DM              refTree;
1186a6f36705SMichael Lange   PetscSection    origParentSection, newParentSection;
1187a6f36705SMichael Lange   PetscInt        *origParents, *origChildIDs;
1188a6f36705SMichael Lange   PetscBool       flg;
1189a6f36705SMichael Lange   PetscErrorCode  ierr;
1190a6f36705SMichael Lange 
1191a6f36705SMichael Lange   PetscFunctionBegin;
1192a6f36705SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1193a6f36705SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 4);
1194a6f36705SMichael Lange   ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
1195a6f36705SMichael Lange 
1196a6f36705SMichael Lange   /* Set up tree */
1197a6f36705SMichael Lange   ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr);
1198a6f36705SMichael Lange   ierr = DMPlexSetReferenceTree(dmParallel,refTree);CHKERRQ(ierr);
1199a6f36705SMichael Lange   ierr = DMPlexGetTree(dm,&origParentSection,&origParents,&origChildIDs,NULL,NULL);CHKERRQ(ierr);
1200a6f36705SMichael Lange   if (origParentSection) {
1201a6f36705SMichael Lange     PetscInt        pStart, pEnd;
120208633170SToby Isaac     PetscInt        *newParents, *newChildIDs, *globParents;
1203a6f36705SMichael Lange     PetscInt        *remoteOffsetsParents, newParentSize;
1204a6f36705SMichael Lange     PetscSF         parentSF;
1205a6f36705SMichael Lange 
1206a6f36705SMichael Lange     ierr = DMPlexGetChart(dmParallel, &pStart, &pEnd);CHKERRQ(ierr);
1207a6f36705SMichael Lange     ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dmParallel),&newParentSection);CHKERRQ(ierr);
1208a6f36705SMichael Lange     ierr = PetscSectionSetChart(newParentSection,pStart,pEnd);CHKERRQ(ierr);
1209a6f36705SMichael Lange     ierr = PetscSFDistributeSection(migrationSF, origParentSection, &remoteOffsetsParents, newParentSection);CHKERRQ(ierr);
1210a6f36705SMichael Lange     ierr = PetscSFCreateSectionSF(migrationSF, origParentSection, remoteOffsetsParents, newParentSection, &parentSF);CHKERRQ(ierr);
12118a713f3bSLawrence Mitchell     ierr = PetscFree(remoteOffsetsParents);CHKERRQ(ierr);
1212a6f36705SMichael Lange     ierr = PetscSectionGetStorageSize(newParentSection,&newParentSize);CHKERRQ(ierr);
1213a6f36705SMichael Lange     ierr = PetscMalloc2(newParentSize,&newParents,newParentSize,&newChildIDs);CHKERRQ(ierr);
121408633170SToby Isaac     if (original) {
121508633170SToby Isaac       PetscInt numParents;
121608633170SToby Isaac 
121708633170SToby Isaac       ierr = PetscSectionGetStorageSize(origParentSection,&numParents);CHKERRQ(ierr);
121808633170SToby Isaac       ierr = PetscMalloc1(numParents,&globParents);CHKERRQ(ierr);
121908633170SToby Isaac       ierr = ISLocalToGlobalMappingApplyBlock(original, numParents, origParents, globParents);CHKERRQ(ierr);
122008633170SToby Isaac     }
122108633170SToby Isaac     else {
122208633170SToby Isaac       globParents = origParents;
122308633170SToby Isaac     }
122408633170SToby Isaac     ierr = PetscSFBcastBegin(parentSF, MPIU_INT, globParents, newParents);CHKERRQ(ierr);
122508633170SToby Isaac     ierr = PetscSFBcastEnd(parentSF, MPIU_INT, globParents, newParents);CHKERRQ(ierr);
122608633170SToby Isaac     if (original) {
122708633170SToby Isaac       ierr = PetscFree(globParents);CHKERRQ(ierr);
122808633170SToby Isaac     }
1229a6f36705SMichael Lange     ierr = PetscSFBcastBegin(parentSF, MPIU_INT, origChildIDs, newChildIDs);CHKERRQ(ierr);
1230a6f36705SMichael Lange     ierr = PetscSFBcastEnd(parentSF, MPIU_INT, origChildIDs, newChildIDs);CHKERRQ(ierr);
1231a6f36705SMichael Lange     ierr = ISGlobalToLocalMappingApplyBlock(renumbering,IS_GTOLM_MASK, newParentSize, newParents, NULL, newParents);CHKERRQ(ierr);
12324a54e071SToby Isaac #if PETSC_USE_DEBUG
12334a54e071SToby Isaac     {
12344a54e071SToby Isaac       PetscInt  p;
12354a54e071SToby Isaac       PetscBool valid = PETSC_TRUE;
12364a54e071SToby Isaac       for (p = 0; p < newParentSize; ++p) {
12374a54e071SToby Isaac         if (newParents[p] < 0) {valid = PETSC_FALSE; ierr = PetscPrintf(PETSC_COMM_SELF, "Point %d not in overlap SF\n", p);CHKERRQ(ierr);}
12384a54e071SToby Isaac       }
12394a54e071SToby Isaac       if (!valid) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid global to local map");
12404a54e071SToby Isaac     }
12414a54e071SToby Isaac #endif
1242c5929fdfSBarry Smith     ierr = PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-parents_view", &flg);CHKERRQ(ierr);
1243a6f36705SMichael Lange     if (flg) {
1244a6f36705SMichael Lange       ierr = PetscPrintf(comm, "Serial Parent Section: \n");CHKERRQ(ierr);
1245a6f36705SMichael Lange       ierr = PetscSectionView(origParentSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
1246a6f36705SMichael Lange       ierr = PetscPrintf(comm, "Parallel Parent Section: \n");CHKERRQ(ierr);
1247a6f36705SMichael Lange       ierr = PetscSectionView(newParentSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
1248a6f36705SMichael Lange       ierr = PetscSFView(parentSF, NULL);CHKERRQ(ierr);
1249a6f36705SMichael Lange     }
1250a6f36705SMichael Lange     ierr = DMPlexSetTree(dmParallel,newParentSection,newParents,newChildIDs);CHKERRQ(ierr);
1251a6f36705SMichael Lange     ierr = PetscSectionDestroy(&newParentSection);CHKERRQ(ierr);
1252a6f36705SMichael Lange     ierr = PetscFree2(newParents,newChildIDs);CHKERRQ(ierr);
1253a6f36705SMichael Lange     ierr = PetscSFDestroy(&parentSF);CHKERRQ(ierr);
1254a6f36705SMichael Lange   }
125515078cd4SMichael Lange   pmesh->useAnchors = mesh->useAnchors;
1256a6f36705SMichael Lange   PetscFunctionReturn(0);
1257a6f36705SMichael Lange }
12580df0e737SMichael Lange 
1259f8987ae8SMichael Lange PetscErrorCode DMPlexDistributeSF(DM dm, PetscSF migrationSF, DM dmParallel)
12604eca1733SMichael Lange {
12614eca1733SMichael Lange   DM_Plex               *mesh  = (DM_Plex*) dm->data;
12624eca1733SMichael Lange   DM_Plex               *pmesh = (DM_Plex*) (dmParallel)->data;
1263*9852e123SBarry Smith   PetscMPIInt            rank, size;
12644eca1733SMichael Lange   MPI_Comm               comm;
12654eca1733SMichael Lange   PetscErrorCode         ierr;
12664eca1733SMichael Lange 
12674eca1733SMichael Lange   PetscFunctionBegin;
12684eca1733SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
12694eca1733SMichael Lange   PetscValidPointer(dmParallel,7);
12704eca1733SMichael Lange 
12714eca1733SMichael Lange   /* Create point SF for parallel mesh */
12724eca1733SMichael Lange   ierr = PetscLogEventBegin(DMPLEX_DistributeSF,dm,0,0,0);CHKERRQ(ierr);
12734eca1733SMichael Lange   ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
12744eca1733SMichael Lange   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
1275*9852e123SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
12764eca1733SMichael Lange   {
12774eca1733SMichael Lange     const PetscInt *leaves;
12784eca1733SMichael Lange     PetscSFNode    *remotePoints, *rowners, *lowners;
12794eca1733SMichael Lange     PetscInt        numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints;
12804eca1733SMichael Lange     PetscInt        pStart, pEnd;
12814eca1733SMichael Lange 
12824eca1733SMichael Lange     ierr = DMPlexGetChart(dmParallel, &pStart, &pEnd);CHKERRQ(ierr);
12834eca1733SMichael Lange     ierr = PetscSFGetGraph(migrationSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr);
12844eca1733SMichael Lange     ierr = PetscMalloc2(numRoots,&rowners,numLeaves,&lowners);CHKERRQ(ierr);
12854eca1733SMichael Lange     for (p=0; p<numRoots; p++) {
12864eca1733SMichael Lange       rowners[p].rank  = -1;
12874eca1733SMichael Lange       rowners[p].index = -1;
12884eca1733SMichael Lange     }
12894eca1733SMichael Lange     ierr = PetscSFBcastBegin(migrationSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
12904eca1733SMichael Lange     ierr = PetscSFBcastEnd(migrationSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
12914eca1733SMichael Lange     for (p = 0; p < numLeaves; ++p) {
12924eca1733SMichael Lange       if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */
12934eca1733SMichael Lange         lowners[p].rank  = rank;
12944eca1733SMichael Lange         lowners[p].index = leaves ? leaves[p] : p;
12954eca1733SMichael Lange       } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */
12964eca1733SMichael Lange         lowners[p].rank  = -2;
12974eca1733SMichael Lange         lowners[p].index = -2;
12984eca1733SMichael Lange       }
12994eca1733SMichael Lange     }
13004eca1733SMichael Lange     for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */
13014eca1733SMichael Lange       rowners[p].rank  = -3;
13024eca1733SMichael Lange       rowners[p].index = -3;
13034eca1733SMichael Lange     }
13044eca1733SMichael Lange     ierr = PetscSFReduceBegin(migrationSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr);
13054eca1733SMichael Lange     ierr = PetscSFReduceEnd(migrationSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr);
13064eca1733SMichael Lange     ierr = PetscSFBcastBegin(migrationSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
13074eca1733SMichael Lange     ierr = PetscSFBcastEnd(migrationSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
13084eca1733SMichael Lange     for (p = 0; p < numLeaves; ++p) {
13094eca1733SMichael Lange       if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed");
13104eca1733SMichael Lange       if (lowners[p].rank != rank) ++numGhostPoints;
13114eca1733SMichael Lange     }
13124eca1733SMichael Lange     ierr = PetscMalloc1(numGhostPoints, &ghostPoints);CHKERRQ(ierr);
13134eca1733SMichael Lange     ierr = PetscMalloc1(numGhostPoints, &remotePoints);CHKERRQ(ierr);
13144eca1733SMichael Lange     for (p = 0, gp = 0; p < numLeaves; ++p) {
13154eca1733SMichael Lange       if (lowners[p].rank != rank) {
13164eca1733SMichael Lange         ghostPoints[gp]        = leaves ? leaves[p] : p;
13174eca1733SMichael Lange         remotePoints[gp].rank  = lowners[p].rank;
13184eca1733SMichael Lange         remotePoints[gp].index = lowners[p].index;
13194eca1733SMichael Lange         ++gp;
13204eca1733SMichael Lange       }
13214eca1733SMichael Lange     }
13224eca1733SMichael Lange     ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr);
13234eca1733SMichael Lange     ierr = PetscSFSetGraph((dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
13244eca1733SMichael Lange     ierr = PetscSFSetFromOptions((dmParallel)->sf);CHKERRQ(ierr);
13254eca1733SMichael Lange   }
13264eca1733SMichael Lange   pmesh->useCone    = mesh->useCone;
13274eca1733SMichael Lange   pmesh->useClosure = mesh->useClosure;
13284eca1733SMichael Lange   ierr = PetscLogEventEnd(DMPLEX_DistributeSF,dm,0,0,0);CHKERRQ(ierr);
13294eca1733SMichael Lange   PetscFunctionReturn(0);
13304eca1733SMichael Lange }
13314eca1733SMichael Lange 
1332f5bf2dbfSMichael Lange /*@C
1333f5bf2dbfSMichael Lange   DMPlexDerivePointSF - Build a point SF from an SF describing a point migration
1334f5bf2dbfSMichael Lange 
1335f5bf2dbfSMichael Lange   Input Parameter:
1336f5bf2dbfSMichael Lange + dm          - The source DMPlex object
1337f5bf2dbfSMichael Lange . migrationSF - The star forest that describes the parallel point remapping
13381627f6ccSMichael Lange . ownership   - Flag causing a vote to determine point ownership
1339f5bf2dbfSMichael Lange 
1340f5bf2dbfSMichael Lange   Output Parameter:
1341f5bf2dbfSMichael Lange - pointSF     - The star forest describing the point overlap in the remapped DM
1342f5bf2dbfSMichael Lange 
1343f5bf2dbfSMichael Lange   Level: developer
1344f5bf2dbfSMichael Lange 
1345f5bf2dbfSMichael Lange .seealso: DMPlexDistribute(), DMPlexDistributeOverlap()
1346f5bf2dbfSMichael Lange @*/
1347f5bf2dbfSMichael Lange PetscErrorCode DMPlexCreatePointSF(DM dm, PetscSF migrationSF, PetscBool ownership, PetscSF *pointSF)
1348f5bf2dbfSMichael Lange {
1349f5bf2dbfSMichael Lange   PetscMPIInt        rank;
13501627f6ccSMichael Lange   PetscInt           p, nroots, nleaves, idx, npointLeaves;
1351f5bf2dbfSMichael Lange   PetscInt          *pointLocal;
1352f5bf2dbfSMichael Lange   const PetscInt    *leaves;
1353f5bf2dbfSMichael Lange   const PetscSFNode *roots;
1354f5bf2dbfSMichael Lange   PetscSFNode       *rootNodes, *leafNodes, *pointRemote;
1355f5bf2dbfSMichael Lange   PetscErrorCode     ierr;
1356f5bf2dbfSMichael Lange 
1357f5bf2dbfSMichael Lange   PetscFunctionBegin;
1358f5bf2dbfSMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1359f5bf2dbfSMichael Lange   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr);
1360f5bf2dbfSMichael Lange 
1361f5bf2dbfSMichael Lange   ierr = PetscSFGetGraph(migrationSF, &nroots, &nleaves, &leaves, &roots);CHKERRQ(ierr);
1362f5bf2dbfSMichael Lange   ierr = PetscMalloc2(nroots, &rootNodes, nleaves, &leafNodes);CHKERRQ(ierr);
1363f5bf2dbfSMichael Lange   if (ownership) {
13641627f6ccSMichael Lange     /* Point ownership vote: Process with highest rank ownes shared points */
1365f5bf2dbfSMichael Lange     for (p = 0; p < nleaves; ++p) {
1366f5bf2dbfSMichael Lange       /* Either put in a bid or we know we own it */
1367f5bf2dbfSMichael Lange       leafNodes[p].rank  = rank;
136843f7d02bSMichael Lange       leafNodes[p].index = p;
1369f5bf2dbfSMichael Lange     }
1370f5bf2dbfSMichael Lange     for (p = 0; p < nroots; p++) {
13711627f6ccSMichael Lange       /* Root must not participate in the reduction, flag so that MAXLOC does not use */
1372f5bf2dbfSMichael Lange       rootNodes[p].rank  = -3;
1373f5bf2dbfSMichael Lange       rootNodes[p].index = -3;
1374f5bf2dbfSMichael Lange     }
1375f5bf2dbfSMichael Lange     ierr = PetscSFReduceBegin(migrationSF, MPIU_2INT, leafNodes, rootNodes, MPI_MAXLOC);CHKERRQ(ierr);
1376f5bf2dbfSMichael Lange     ierr = PetscSFReduceEnd(migrationSF, MPIU_2INT, leafNodes, rootNodes, MPI_MAXLOC);CHKERRQ(ierr);
1377f5bf2dbfSMichael Lange   } else {
1378f5bf2dbfSMichael Lange     for (p = 0; p < nroots; p++) {
1379f5bf2dbfSMichael Lange       rootNodes[p].index = -1;
1380f5bf2dbfSMichael Lange       rootNodes[p].rank = rank;
1381f5bf2dbfSMichael Lange     };
1382f5bf2dbfSMichael Lange     for (p = 0; p < nleaves; p++) {
1383f5bf2dbfSMichael Lange       /* Write new local id into old location */
1384f5bf2dbfSMichael Lange       if (roots[p].rank == rank) {
13856462276dSToby Isaac         rootNodes[roots[p].index].index = leaves ? leaves[p] : p;
1386f5bf2dbfSMichael Lange       }
1387f5bf2dbfSMichael Lange     }
1388f5bf2dbfSMichael Lange   }
1389f5bf2dbfSMichael Lange   ierr = PetscSFBcastBegin(migrationSF, MPIU_2INT, rootNodes, leafNodes);CHKERRQ(ierr);
1390f5bf2dbfSMichael Lange   ierr = PetscSFBcastEnd(migrationSF, MPIU_2INT, rootNodes, leafNodes);CHKERRQ(ierr);
1391f5bf2dbfSMichael Lange 
1392f5bf2dbfSMichael Lange   for (npointLeaves = 0, p = 0; p < nleaves; p++) {if (leafNodes[p].rank != rank) npointLeaves++;}
13931627f6ccSMichael Lange   ierr = PetscMalloc1(npointLeaves, &pointLocal);CHKERRQ(ierr);
13941627f6ccSMichael Lange   ierr = PetscMalloc1(npointLeaves, &pointRemote);CHKERRQ(ierr);
1395f5bf2dbfSMichael Lange   for (idx = 0, p = 0; p < nleaves; p++) {
1396f5bf2dbfSMichael Lange     if (leafNodes[p].rank != rank) {
1397f5bf2dbfSMichael Lange       pointLocal[idx] = p;
1398f5bf2dbfSMichael Lange       pointRemote[idx] = leafNodes[p];
1399f5bf2dbfSMichael Lange       idx++;
1400f5bf2dbfSMichael Lange     }
1401f5bf2dbfSMichael Lange   }
1402f5bf2dbfSMichael Lange   ierr = PetscSFCreate(PetscObjectComm((PetscObject) dm), pointSF);CHKERRQ(ierr);
14031627f6ccSMichael Lange   ierr = PetscSFSetFromOptions(*pointSF);CHKERRQ(ierr);
1404f5bf2dbfSMichael Lange   ierr = PetscSFSetGraph(*pointSF, nleaves, npointLeaves, pointLocal, PETSC_OWN_POINTER, pointRemote, PETSC_OWN_POINTER);CHKERRQ(ierr);
1405f5bf2dbfSMichael Lange   ierr = PetscFree2(rootNodes, leafNodes);CHKERRQ(ierr);
1406f5bf2dbfSMichael Lange   PetscFunctionReturn(0);
1407f5bf2dbfSMichael Lange }
1408f5bf2dbfSMichael Lange 
140915078cd4SMichael Lange /*@C
141015078cd4SMichael Lange   DMPlexMigrate  - Migrates internal DM data over the supplied star forest
141115078cd4SMichael Lange 
141215078cd4SMichael Lange   Input Parameter:
141315078cd4SMichael Lange + dm       - The source DMPlex object
14141627f6ccSMichael Lange . sf       - The star forest communication context describing the migration pattern
141515078cd4SMichael Lange 
141615078cd4SMichael Lange   Output Parameter:
141715078cd4SMichael Lange - targetDM - The target DMPlex object
141815078cd4SMichael Lange 
1419b9f40539SMichael Lange   Level: intermediate
142015078cd4SMichael Lange 
142115078cd4SMichael Lange .seealso: DMPlexDistribute(), DMPlexDistributeOverlap()
142215078cd4SMichael Lange @*/
1423b9f40539SMichael Lange PetscErrorCode DMPlexMigrate(DM dm, PetscSF sf, DM targetDM)
142415078cd4SMichael Lange {
1425b9f40539SMichael Lange   MPI_Comm               comm;
1426b9f40539SMichael Lange   PetscInt               dim, nroots;
1427b9f40539SMichael Lange   PetscSF                sfPoint;
142815078cd4SMichael Lange   ISLocalToGlobalMapping ltogMigration;
1429ac04eaf7SToby Isaac   ISLocalToGlobalMapping ltogOriginal = NULL;
1430b9f40539SMichael Lange   PetscBool              flg;
143115078cd4SMichael Lange   PetscErrorCode         ierr;
143215078cd4SMichael Lange 
143315078cd4SMichael Lange   PetscFunctionBegin;
143415078cd4SMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14351b858b30SMichael Lange   ierr = PetscLogEventBegin(DMPLEX_Migrate, dm, 0, 0, 0);CHKERRQ(ierr);
1436b9f40539SMichael Lange   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
143715078cd4SMichael Lange   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
143815078cd4SMichael Lange   ierr = DMSetDimension(targetDM, dim);CHKERRQ(ierr);
143915078cd4SMichael Lange 
1440bfb0467fSMichael Lange   /* Check for a one-to-all distribution pattern */
1441b9f40539SMichael Lange   ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
1442b9f40539SMichael Lange   ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
1443bfb0467fSMichael Lange   if (nroots >= 0) {
1444b9f40539SMichael Lange     IS                     isOriginal;
1445ac04eaf7SToby Isaac     PetscInt               n, size, nleaves;
1446ac04eaf7SToby Isaac     PetscInt              *numbering_orig, *numbering_new;
1447b9f40539SMichael Lange     /* Get the original point numbering */
1448b9f40539SMichael Lange     ierr = DMPlexCreatePointNumbering(dm, &isOriginal);CHKERRQ(ierr);
1449b9f40539SMichael Lange     ierr = ISLocalToGlobalMappingCreateIS(isOriginal, &ltogOriginal);CHKERRQ(ierr);
1450b9f40539SMichael Lange     ierr = ISLocalToGlobalMappingGetSize(ltogOriginal, &size);CHKERRQ(ierr);
1451b9f40539SMichael Lange     ierr = ISLocalToGlobalMappingGetBlockIndices(ltogOriginal, (const PetscInt**)&numbering_orig);CHKERRQ(ierr);
1452b9f40539SMichael Lange     /* Convert to positive global numbers */
1453b9f40539SMichael Lange     for (n=0; n<size; n++) {if (numbering_orig[n] < 0) numbering_orig[n] = -(numbering_orig[n]+1);}
1454b9f40539SMichael Lange     /* Derive the new local-to-global mapping from the old one */
1455b9f40539SMichael Lange     ierr = PetscSFGetGraph(sf, NULL, &nleaves, NULL, NULL);CHKERRQ(ierr);
1456b9f40539SMichael Lange     ierr = PetscMalloc1(nleaves, &numbering_new);CHKERRQ(ierr);
1457b9f40539SMichael Lange     ierr = PetscSFBcastBegin(sf, MPIU_INT, (PetscInt *) numbering_orig, numbering_new);CHKERRQ(ierr);
1458b9f40539SMichael Lange     ierr = PetscSFBcastEnd(sf, MPIU_INT, (PetscInt *) numbering_orig, numbering_new);CHKERRQ(ierr);
1459b9f40539SMichael Lange     ierr = ISLocalToGlobalMappingCreate(comm, 1, nleaves, (const PetscInt*) numbering_new, PETSC_OWN_POINTER, &ltogMigration);CHKERRQ(ierr);
1460b9f40539SMichael Lange     ierr = ISLocalToGlobalMappingRestoreIndices(ltogOriginal, (const PetscInt**)&numbering_orig);CHKERRQ(ierr);
1461b9f40539SMichael Lange     ierr = ISDestroy(&isOriginal);CHKERRQ(ierr);
146215078cd4SMichael Lange   } else {
1463bfb0467fSMichael Lange     /* One-to-all distribution pattern: We can derive LToG from SF */
146415078cd4SMichael Lange     ierr = ISLocalToGlobalMappingCreateSF(sf, 0, &ltogMigration);CHKERRQ(ierr);
146515078cd4SMichael Lange   }
1466c5929fdfSBarry Smith   ierr = PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr);
1467b9f40539SMichael Lange   if (flg) {
1468b9f40539SMichael Lange     ierr = PetscPrintf(comm, "Point renumbering for DM migration:\n");CHKERRQ(ierr);
1469b9f40539SMichael Lange     ierr = ISLocalToGlobalMappingView(ltogMigration, NULL);CHKERRQ(ierr);
1470b9f40539SMichael Lange   }
147115078cd4SMichael Lange   /* Migrate DM data to target DM */
1472ac04eaf7SToby Isaac   ierr = DMPlexDistributeCones(dm, sf, ltogOriginal, ltogMigration, targetDM);CHKERRQ(ierr);
147315078cd4SMichael Lange   ierr = DMPlexDistributeLabels(dm, sf, targetDM);CHKERRQ(ierr);
14740dc1530dSSander Arens   ierr = DMPlexDistributeCoordinates(dm, sf, targetDM);CHKERRQ(ierr);
147515078cd4SMichael Lange   ierr = DMPlexDistributeSetupHybrid(dm, sf, ltogMigration, targetDM);CHKERRQ(ierr);
147608633170SToby Isaac   ierr = DMPlexDistributeSetupTree(dm, sf, ltogOriginal, ltogMigration, targetDM);CHKERRQ(ierr);
1477ac04eaf7SToby Isaac   ierr = ISLocalToGlobalMappingDestroy(&ltogOriginal);CHKERRQ(ierr);
1478302440fdSBarry Smith   ierr = ISLocalToGlobalMappingDestroy(&ltogMigration);CHKERRQ(ierr);
14791b858b30SMichael Lange   ierr = PetscLogEventEnd(DMPLEX_Migrate, dm, 0, 0, 0);CHKERRQ(ierr);
148015078cd4SMichael Lange   PetscFunctionReturn(0);
148115078cd4SMichael Lange }
148215078cd4SMichael Lange 
14833b8f15a2SMatthew G. Knepley /*@C
148470034214SMatthew G. Knepley   DMPlexDistribute - Distributes the mesh and any associated sections.
148570034214SMatthew G. Knepley 
148670034214SMatthew G. Knepley   Not Collective
148770034214SMatthew G. Knepley 
148870034214SMatthew G. Knepley   Input Parameter:
148970034214SMatthew G. Knepley + dm  - The original DMPlex object
149070034214SMatthew G. Knepley - overlap - The overlap of partitions, 0 is the default
149170034214SMatthew G. Knepley 
149270034214SMatthew G. Knepley   Output Parameter:
149370034214SMatthew G. Knepley + sf - The PetscSF used for point distribution
149470034214SMatthew G. Knepley - parallelMesh - The distributed DMPlex object, or NULL
149570034214SMatthew G. Knepley 
149670034214SMatthew G. Knepley   Note: If the mesh was not distributed, the return value is NULL.
149770034214SMatthew G. Knepley 
149893a1dc33SMatthew G. Knepley   The user can control the definition of adjacency for the mesh using DMPlexSetAdjacencyUseCone() and
149970034214SMatthew G. Knepley   DMPlexSetAdjacencyUseClosure(). They should choose the combination appropriate for the function
150070034214SMatthew G. Knepley   representation on the mesh.
150170034214SMatthew G. Knepley 
150270034214SMatthew G. Knepley   Level: intermediate
150370034214SMatthew G. Knepley 
150470034214SMatthew G. Knepley .keywords: mesh, elements
150570034214SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexDistributeByFace(), DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure()
150670034214SMatthew G. Knepley @*/
150780cf41d5SMatthew G. Knepley PetscErrorCode DMPlexDistribute(DM dm, PetscInt overlap, PetscSF *sf, DM *dmParallel)
150870034214SMatthew G. Knepley {
150970034214SMatthew G. Knepley   MPI_Comm               comm;
151015078cd4SMichael Lange   PetscPartitioner       partitioner;
1511f8987ae8SMichael Lange   IS                     cellPart;
1512f8987ae8SMichael Lange   PetscSection           cellPartSection;
1513cf86098cSMatthew G. Knepley   DM                     dmCoord;
1514f8987ae8SMichael Lange   DMLabel                lblPartition, lblMigration;
151543f7d02bSMichael Lange   PetscSF                sfProcess, sfMigration, sfStratified, sfPoint;
151670034214SMatthew G. Knepley   PetscBool              flg;
1517*9852e123SBarry Smith   PetscMPIInt            rank, size, p;
151870034214SMatthew G. Knepley   PetscErrorCode         ierr;
151970034214SMatthew G. Knepley 
152070034214SMatthew G. Knepley   PetscFunctionBegin;
152170034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
152270034214SMatthew G. Knepley   if (sf) PetscValidPointer(sf,4);
152370034214SMatthew G. Knepley   PetscValidPointer(dmParallel,5);
152470034214SMatthew G. Knepley 
152570034214SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr);
152670034214SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
152770034214SMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
1528*9852e123SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
152970034214SMatthew G. Knepley 
153070034214SMatthew G. Knepley   *dmParallel = NULL;
1531*9852e123SBarry Smith   if (size == 1) {
15325f3267c8SKoos Huijssen     ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr);
15335f3267c8SKoos Huijssen     PetscFunctionReturn(0);
15345f3267c8SKoos Huijssen   }
153570034214SMatthew G. Knepley 
153615078cd4SMichael Lange   /* Create cell partition */
153777623264SMatthew G. Knepley   ierr = PetscLogEventBegin(PETSCPARTITIONER_Partition,dm,0,0,0);CHKERRQ(ierr);
153877623264SMatthew G. Knepley   ierr = PetscSectionCreate(comm, &cellPartSection);CHKERRQ(ierr);
153915078cd4SMichael Lange   ierr = DMPlexGetPartitioner(dm, &partitioner);CHKERRQ(ierr);
154015078cd4SMichael Lange   ierr = PetscPartitionerPartition(partitioner, dm, cellPartSection, &cellPart);CHKERRQ(ierr);
1541f8987ae8SMichael Lange   {
1542f8987ae8SMichael Lange     /* Convert partition to DMLabel */
1543f8987ae8SMichael Lange     PetscInt proc, pStart, pEnd, npoints, poffset;
1544f8987ae8SMichael Lange     const PetscInt *points;
1545f8987ae8SMichael Lange     ierr = DMLabelCreate("Point Partition", &lblPartition);CHKERRQ(ierr);
1546f8987ae8SMichael Lange     ierr = ISGetIndices(cellPart, &points);CHKERRQ(ierr);
1547f8987ae8SMichael Lange     ierr = PetscSectionGetChart(cellPartSection, &pStart, &pEnd);CHKERRQ(ierr);
1548f8987ae8SMichael Lange     for (proc = pStart; proc < pEnd; proc++) {
1549f8987ae8SMichael Lange       ierr = PetscSectionGetDof(cellPartSection, proc, &npoints);CHKERRQ(ierr);
1550f8987ae8SMichael Lange       ierr = PetscSectionGetOffset(cellPartSection, proc, &poffset);CHKERRQ(ierr);
1551f8987ae8SMichael Lange       for (p = poffset; p < poffset+npoints; p++) {
1552f8987ae8SMichael Lange         ierr = DMLabelSetValue(lblPartition, points[p], proc);CHKERRQ(ierr);
155370034214SMatthew G. Knepley       }
1554f8987ae8SMichael Lange     }
1555f8987ae8SMichael Lange     ierr = ISRestoreIndices(cellPart, &points);CHKERRQ(ierr);
1556f8987ae8SMichael Lange   }
1557f8987ae8SMichael Lange   ierr = DMPlexPartitionLabelClosure(dm, lblPartition);CHKERRQ(ierr);
1558f8987ae8SMichael Lange   {
1559f8987ae8SMichael Lange     /* Build a global process SF */
1560f8987ae8SMichael Lange     PetscSFNode *remoteProc;
1561*9852e123SBarry Smith     ierr = PetscMalloc1(size, &remoteProc);CHKERRQ(ierr);
1562*9852e123SBarry Smith     for (p = 0; p < size; ++p) {
1563f8987ae8SMichael Lange       remoteProc[p].rank  = p;
1564f8987ae8SMichael Lange       remoteProc[p].index = rank;
1565f8987ae8SMichael Lange     }
1566f8987ae8SMichael Lange     ierr = PetscSFCreate(comm, &sfProcess);CHKERRQ(ierr);
1567f8987ae8SMichael Lange     ierr = PetscObjectSetName((PetscObject) sfProcess, "Process SF");CHKERRQ(ierr);
1568*9852e123SBarry Smith     ierr = PetscSFSetGraph(sfProcess, size, size, NULL, PETSC_OWN_POINTER, remoteProc, PETSC_OWN_POINTER);CHKERRQ(ierr);
1569f8987ae8SMichael Lange   }
1570f8987ae8SMichael Lange   ierr = DMLabelCreate("Point migration", &lblMigration);CHKERRQ(ierr);
1571f8987ae8SMichael Lange   ierr = DMPlexPartitionLabelInvert(dm, lblPartition, sfProcess, lblMigration);CHKERRQ(ierr);
1572302440fdSBarry Smith   ierr = DMPlexPartitionLabelCreateSF(dm, lblMigration, &sfMigration);CHKERRQ(ierr);
157343f7d02bSMichael Lange   /* Stratify the SF in case we are migrating an already parallel plex */
157443f7d02bSMichael Lange   ierr = DMPlexStratifyMigrationSF(dm, sfMigration, &sfStratified);CHKERRQ(ierr);
157543f7d02bSMichael Lange   ierr = PetscSFDestroy(&sfMigration);CHKERRQ(ierr);
157643f7d02bSMichael Lange   sfMigration = sfStratified;
1577f8987ae8SMichael Lange   ierr = PetscLogEventEnd(PETSCPARTITIONER_Partition,dm,0,0,0);CHKERRQ(ierr);
1578c5929fdfSBarry Smith   ierr = PetscOptionsHasName(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr);
157970034214SMatthew G. Knepley   if (flg) {
1580f8987ae8SMichael Lange     ierr = DMLabelView(lblPartition, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
1581f8987ae8SMichael Lange     ierr = PetscSFView(sfMigration, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
158270034214SMatthew G. Knepley   }
1583f8987ae8SMichael Lange 
158415078cd4SMichael Lange   /* Create non-overlapping parallel DM and migrate internal data */
158570034214SMatthew G. Knepley   ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr);
158670034214SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr);
1587b9f40539SMichael Lange   ierr = DMPlexMigrate(dm, sfMigration, *dmParallel);CHKERRQ(ierr);
158870034214SMatthew G. Knepley 
1589a157612eSMichael Lange   /* Build the point SF without overlap */
15901627f6ccSMichael Lange   ierr = DMPlexCreatePointSF(*dmParallel, sfMigration, PETSC_TRUE, &sfPoint);CHKERRQ(ierr);
1591f5bf2dbfSMichael Lange   ierr = DMSetPointSF(*dmParallel, sfPoint);CHKERRQ(ierr);
1592cf86098cSMatthew G. Knepley   ierr = DMGetCoordinateDM(*dmParallel, &dmCoord);CHKERRQ(ierr);
1593cf86098cSMatthew G. Knepley   if (dmCoord) {ierr = DMSetPointSF(dmCoord, sfPoint);CHKERRQ(ierr);}
1594f5bf2dbfSMichael Lange   if (flg) {ierr = PetscSFView(sfPoint, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);}
159570034214SMatthew G. Knepley 
1596a157612eSMichael Lange   if (overlap > 0) {
159715078cd4SMichael Lange     DM                 dmOverlap;
159815078cd4SMichael Lange     PetscInt           nroots, nleaves;
159915078cd4SMichael Lange     PetscSFNode       *newRemote;
160015078cd4SMichael Lange     const PetscSFNode *oldRemote;
160115078cd4SMichael Lange     PetscSF            sfOverlap, sfOverlapPoint;
1602a157612eSMichael Lange     /* Add the partition overlap to the distributed DM */
1603b9f40539SMichael Lange     ierr = DMPlexDistributeOverlap(*dmParallel, overlap, &sfOverlap, &dmOverlap);CHKERRQ(ierr);
1604a157612eSMichael Lange     ierr = DMDestroy(dmParallel);CHKERRQ(ierr);
1605a157612eSMichael Lange     *dmParallel = dmOverlap;
1606c389ea9fSToby Isaac     if (flg) {
16073d822a50SMichael Lange       ierr = PetscPrintf(comm, "Overlap Migration SF:\n");CHKERRQ(ierr);
160815078cd4SMichael Lange       ierr = PetscSFView(sfOverlap, NULL);CHKERRQ(ierr);
1609c389ea9fSToby Isaac     }
161043331d4aSMichael Lange 
1611f8987ae8SMichael Lange     /* Re-map the migration SF to establish the full migration pattern */
1612f8987ae8SMichael Lange     ierr = PetscSFGetGraph(sfMigration, &nroots, NULL, NULL, &oldRemote);CHKERRQ(ierr);
161315078cd4SMichael Lange     ierr = PetscSFGetGraph(sfOverlap, NULL, &nleaves, NULL, NULL);CHKERRQ(ierr);
161443331d4aSMichael Lange     ierr = PetscMalloc1(nleaves, &newRemote);CHKERRQ(ierr);
161515078cd4SMichael Lange     ierr = PetscSFBcastBegin(sfOverlap, MPIU_2INT, oldRemote, newRemote);CHKERRQ(ierr);
161615078cd4SMichael Lange     ierr = PetscSFBcastEnd(sfOverlap, MPIU_2INT, oldRemote, newRemote);CHKERRQ(ierr);
161715078cd4SMichael Lange     ierr = PetscSFCreate(comm, &sfOverlapPoint);CHKERRQ(ierr);
161815078cd4SMichael Lange     ierr = PetscSFSetGraph(sfOverlapPoint, nroots, nleaves, NULL, PETSC_OWN_POINTER, newRemote, PETSC_OWN_POINTER);CHKERRQ(ierr);
161915078cd4SMichael Lange     ierr = PetscSFDestroy(&sfOverlap);CHKERRQ(ierr);
1620f8987ae8SMichael Lange     ierr = PetscSFDestroy(&sfMigration);CHKERRQ(ierr);
162115078cd4SMichael Lange     sfMigration = sfOverlapPoint;
1622c389ea9fSToby Isaac   }
1623bf5244c7SMatthew G. Knepley   /* Cleanup Partition */
1624f8987ae8SMichael Lange   ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr);
1625f8987ae8SMichael Lange   ierr = DMLabelDestroy(&lblPartition);CHKERRQ(ierr);
1626f8987ae8SMichael Lange   ierr = DMLabelDestroy(&lblMigration);CHKERRQ(ierr);
16274eca1733SMichael Lange   ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr);
16284eca1733SMichael Lange   ierr = ISDestroy(&cellPart);CHKERRQ(ierr);
1629721cbd76SMatthew G. Knepley   /* Copy BC */
1630a6ba4734SToby Isaac   ierr = DMCopyBoundary(dm, *dmParallel);CHKERRQ(ierr);
163166fe0bfeSMatthew G. Knepley   /* Create sfNatural */
163266fe0bfeSMatthew G. Knepley   if (dm->useNatural) {
163366fe0bfeSMatthew G. Knepley     PetscSection section;
163466fe0bfeSMatthew G. Knepley 
163566fe0bfeSMatthew G. Knepley     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
16360c1f158bSMatthew G. Knepley     ierr = DMPlexCreateGlobalToNaturalSF(*dmParallel, section, sfMigration, &(*dmParallel)->sfNatural);CHKERRQ(ierr);
163766fe0bfeSMatthew G. Knepley   }
1638721cbd76SMatthew G. Knepley   /* Cleanup */
1639f8987ae8SMichael Lange   if (sf) {*sf = sfMigration;}
1640f8987ae8SMichael Lange   else    {ierr = PetscSFDestroy(&sfMigration);CHKERRQ(ierr);}
1641f5bf2dbfSMichael Lange   ierr = PetscSFDestroy(&sfPoint);CHKERRQ(ierr);
164270034214SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr);
164370034214SMatthew G. Knepley   PetscFunctionReturn(0);
164470034214SMatthew G. Knepley }
1645a157612eSMichael Lange 
1646a157612eSMichael Lange /*@C
1647a157612eSMichael Lange   DMPlexDistribute - Add partition overlap to a distributed non-overlapping DM.
1648a157612eSMichael Lange 
1649a157612eSMichael Lange   Not Collective
1650a157612eSMichael Lange 
1651a157612eSMichael Lange   Input Parameter:
1652a157612eSMichael Lange + dm  - The non-overlapping distrbuted DMPlex object
1653a157612eSMichael Lange - overlap - The overlap of partitions, 0 is the default
1654a157612eSMichael Lange 
1655a157612eSMichael Lange   Output Parameter:
1656a157612eSMichael Lange + sf - The PetscSF used for point distribution
1657a157612eSMichael Lange - dmOverlap - The overlapping distributed DMPlex object, or NULL
1658a157612eSMichael Lange 
1659a157612eSMichael Lange   Note: If the mesh was not distributed, the return value is NULL.
1660a157612eSMichael Lange 
1661a157612eSMichael Lange   The user can control the definition of adjacency for the mesh using DMPlexGetAdjacencyUseCone() and
1662a157612eSMichael Lange   DMPlexSetAdjacencyUseClosure(). They should choose the combination appropriate for the function
1663a157612eSMichael Lange   representation on the mesh.
1664a157612eSMichael Lange 
1665a157612eSMichael Lange   Level: intermediate
1666a157612eSMichael Lange 
1667a157612eSMichael Lange .keywords: mesh, elements
1668a157612eSMichael Lange .seealso: DMPlexCreate(), DMPlexDistributeByFace(), DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure()
1669a157612eSMichael Lange @*/
1670b9f40539SMichael Lange PetscErrorCode DMPlexDistributeOverlap(DM dm, PetscInt overlap, PetscSF *sf, DM *dmOverlap)
1671a157612eSMichael Lange {
1672a157612eSMichael Lange   MPI_Comm               comm;
1673a157612eSMichael Lange   PetscMPIInt            rank;
1674a157612eSMichael Lange   PetscSection           rootSection, leafSection;
1675a157612eSMichael Lange   IS                     rootrank, leafrank;
1676cf86098cSMatthew G. Knepley   DM                     dmCoord;
1677a9f1d5b2SMichael Lange   DMLabel                lblOverlap;
1678f5bf2dbfSMichael Lange   PetscSF                sfOverlap, sfStratified, sfPoint;
1679a157612eSMichael Lange   PetscErrorCode         ierr;
1680a157612eSMichael Lange 
1681a157612eSMichael Lange   PetscFunctionBegin;
1682a157612eSMichael Lange   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1683a157612eSMichael Lange   if (sf) PetscValidPointer(sf, 3);
1684a157612eSMichael Lange   PetscValidPointer(dmOverlap, 4);
1685a157612eSMichael Lange 
16861b858b30SMichael Lange   ierr = PetscLogEventBegin(DMPLEX_DistributeOverlap, dm, 0, 0, 0);CHKERRQ(ierr);
1687a157612eSMichael Lange   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1688a157612eSMichael Lange   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
1689a157612eSMichael Lange 
1690a157612eSMichael Lange   /* Compute point overlap with neighbouring processes on the distributed DM */
1691a157612eSMichael Lange   ierr = PetscLogEventBegin(PETSCPARTITIONER_Partition,dm,0,0,0);CHKERRQ(ierr);
1692a157612eSMichael Lange   ierr = PetscSectionCreate(comm, &rootSection);CHKERRQ(ierr);
1693a157612eSMichael Lange   ierr = PetscSectionCreate(comm, &leafSection);CHKERRQ(ierr);
1694a157612eSMichael Lange   ierr = DMPlexDistributeOwnership(dm, rootSection, &rootrank, leafSection, &leafrank);CHKERRQ(ierr);
1695a9f1d5b2SMichael Lange   ierr = DMPlexCreateOverlap(dm, overlap, rootSection, rootrank, leafSection, leafrank, &lblOverlap);CHKERRQ(ierr);
1696a9f1d5b2SMichael Lange   /* Convert overlap label to stratified migration SF */
1697a9f1d5b2SMichael Lange   ierr = DMPlexPartitionLabelCreateSF(dm, lblOverlap, &sfOverlap);CHKERRQ(ierr);
1698a9f1d5b2SMichael Lange   ierr = DMPlexStratifyMigrationSF(dm, sfOverlap, &sfStratified);CHKERRQ(ierr);
1699a9f1d5b2SMichael Lange   ierr = PetscSFDestroy(&sfOverlap);CHKERRQ(ierr);
1700a9f1d5b2SMichael Lange   sfOverlap = sfStratified;
1701a9f1d5b2SMichael Lange   ierr = PetscObjectSetName((PetscObject) sfOverlap, "Overlap SF");CHKERRQ(ierr);
1702a9f1d5b2SMichael Lange   ierr = PetscSFSetFromOptions(sfOverlap);CHKERRQ(ierr);
1703a9f1d5b2SMichael Lange 
170415fff7beSMatthew G. Knepley   ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr);
170515fff7beSMatthew G. Knepley   ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr);
170615fff7beSMatthew G. Knepley   ierr = ISDestroy(&rootrank);CHKERRQ(ierr);
170715fff7beSMatthew G. Knepley   ierr = ISDestroy(&leafrank);CHKERRQ(ierr);
1708a157612eSMichael Lange   ierr = PetscLogEventEnd(PETSCPARTITIONER_Partition,dm,0,0,0);CHKERRQ(ierr);
1709a157612eSMichael Lange 
1710a157612eSMichael Lange   /* Build the overlapping DM */
1711a157612eSMichael Lange   ierr = DMPlexCreate(comm, dmOverlap);CHKERRQ(ierr);
1712a157612eSMichael Lange   ierr = PetscObjectSetName((PetscObject) *dmOverlap, "Parallel Mesh");CHKERRQ(ierr);
1713a9f1d5b2SMichael Lange   ierr = DMPlexMigrate(dm, sfOverlap, *dmOverlap);CHKERRQ(ierr);
1714f5bf2dbfSMichael Lange   /* Build the new point SF */
17151627f6ccSMichael Lange   ierr = DMPlexCreatePointSF(*dmOverlap, sfOverlap, PETSC_FALSE, &sfPoint);CHKERRQ(ierr);
1716f5bf2dbfSMichael Lange   ierr = DMSetPointSF(*dmOverlap, sfPoint);CHKERRQ(ierr);
1717cf86098cSMatthew G. Knepley   ierr = DMGetCoordinateDM(*dmOverlap, &dmCoord);CHKERRQ(ierr);
1718cf86098cSMatthew G. Knepley   if (dmCoord) {ierr = DMSetPointSF(dmCoord, sfPoint);CHKERRQ(ierr);}
1719f5bf2dbfSMichael Lange   ierr = PetscSFDestroy(&sfPoint);CHKERRQ(ierr);
1720a157612eSMichael Lange   /* Cleanup overlap partition */
1721a9f1d5b2SMichael Lange   ierr = DMLabelDestroy(&lblOverlap);CHKERRQ(ierr);
1722a9f1d5b2SMichael Lange   if (sf) *sf = sfOverlap;
1723a9f1d5b2SMichael Lange   else    {ierr = PetscSFDestroy(&sfOverlap);CHKERRQ(ierr);}
17241b858b30SMichael Lange   ierr = PetscLogEventEnd(DMPLEX_DistributeOverlap, dm, 0, 0, 0);CHKERRQ(ierr);
1725a157612eSMichael Lange   PetscFunctionReturn(0);
1726a157612eSMichael Lange }
17276462276dSToby Isaac 
17286462276dSToby Isaac /*@C
17296462276dSToby Isaac   DMPlexGetGatherDM - Get a copy of the DMPlex that gathers all points on the
17306462276dSToby Isaac   root process of the original's communicator.
17316462276dSToby Isaac 
17326462276dSToby Isaac   Input Parameters:
17336462276dSToby Isaac . dm - the original DMPlex object
17346462276dSToby Isaac 
17356462276dSToby Isaac   Output Parameters:
17366462276dSToby Isaac . gatherMesh - the gathered DM object, or NULL
17376462276dSToby Isaac 
17386462276dSToby Isaac   Level: intermediate
17396462276dSToby Isaac 
17406462276dSToby Isaac .keywords: mesh
17416462276dSToby Isaac .seealso: DMPlexDistribute(), DMPlexGetRedundantDM()
17426462276dSToby Isaac @*/
17436462276dSToby Isaac PetscErrorCode DMPlexGetGatherDM(DM dm, DM * gatherMesh)
17446462276dSToby Isaac {
17456462276dSToby Isaac   MPI_Comm       comm;
17466462276dSToby Isaac   PetscMPIInt    size;
17476462276dSToby Isaac   PetscPartitioner oldPart, gatherPart;
17486462276dSToby Isaac   PetscErrorCode ierr;
17496462276dSToby Isaac 
17506462276dSToby Isaac   PetscFunctionBegin;
17516462276dSToby Isaac   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
17526462276dSToby Isaac   comm = PetscObjectComm((PetscObject)dm);
17536462276dSToby Isaac   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
17546462276dSToby Isaac   *gatherMesh = NULL;
17556462276dSToby Isaac   if (size == 1) PetscFunctionReturn(0);
17566462276dSToby Isaac   ierr = DMPlexGetPartitioner(dm,&oldPart);CHKERRQ(ierr);
17576462276dSToby Isaac   ierr = PetscObjectReference((PetscObject)oldPart);CHKERRQ(ierr);
17586462276dSToby Isaac   ierr = PetscPartitionerCreate(comm,&gatherPart);CHKERRQ(ierr);
17596462276dSToby Isaac   ierr = PetscPartitionerSetType(gatherPart,PETSCPARTITIONERGATHER);CHKERRQ(ierr);
17606462276dSToby Isaac   ierr = DMPlexSetPartitioner(dm,gatherPart);CHKERRQ(ierr);
17616462276dSToby Isaac   ierr = DMPlexDistribute(dm,0,NULL,gatherMesh);CHKERRQ(ierr);
17626462276dSToby Isaac   ierr = DMPlexSetPartitioner(dm,oldPart);CHKERRQ(ierr);
17636462276dSToby Isaac   ierr = PetscPartitionerDestroy(&gatherPart);CHKERRQ(ierr);
17646462276dSToby Isaac   ierr = PetscPartitionerDestroy(&oldPart);CHKERRQ(ierr);
17656462276dSToby Isaac   PetscFunctionReturn(0);
17666462276dSToby Isaac }
17676462276dSToby Isaac 
17686462276dSToby Isaac /*@C
17696462276dSToby Isaac   DMPlexGetRedundantDM - Get a copy of the DMPlex that is completely copied on each process.
17706462276dSToby Isaac 
17716462276dSToby Isaac   Input Parameters:
17726462276dSToby Isaac . dm - the original DMPlex object
17736462276dSToby Isaac 
17746462276dSToby Isaac   Output Parameters:
17756462276dSToby Isaac . redundantMesh - the redundant DM object, or NULL
17766462276dSToby Isaac 
17776462276dSToby Isaac   Level: intermediate
17786462276dSToby Isaac 
17796462276dSToby Isaac .keywords: mesh
17806462276dSToby Isaac .seealso: DMPlexDistribute(), DMPlexGetGatherDM()
17816462276dSToby Isaac @*/
17826462276dSToby Isaac PetscErrorCode DMPlexGetRedundantDM(DM dm, DM * redundantMesh)
17836462276dSToby Isaac {
17846462276dSToby Isaac   MPI_Comm       comm;
17856462276dSToby Isaac   PetscMPIInt    size, rank;
17866462276dSToby Isaac   PetscInt       pStart, pEnd, p;
17876462276dSToby Isaac   PetscInt       numPoints = -1;
17886462276dSToby Isaac   PetscSF        migrationSF, sfPoint;
17896462276dSToby Isaac   DM             gatherDM, dmCoord;
17906462276dSToby Isaac   PetscSFNode    *points;
17916462276dSToby Isaac   PetscErrorCode ierr;
17926462276dSToby Isaac 
17936462276dSToby Isaac   PetscFunctionBegin;
17946462276dSToby Isaac   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
17956462276dSToby Isaac   comm = PetscObjectComm((PetscObject)dm);
17966462276dSToby Isaac   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
17976462276dSToby Isaac   *redundantMesh = NULL;
179868dbc166SMatthew G. Knepley   if (size == 1) {
179968dbc166SMatthew G. Knepley     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
180068dbc166SMatthew G. Knepley     *redundantMesh = dm;
180168dbc166SMatthew G. Knepley     PetscFunctionReturn(0);
180268dbc166SMatthew G. Knepley   }
18036462276dSToby Isaac   ierr = DMPlexGetGatherDM(dm,&gatherDM);CHKERRQ(ierr);
18046462276dSToby Isaac   if (!gatherDM) PetscFunctionReturn(0);
18056462276dSToby Isaac   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
18066462276dSToby Isaac   ierr = DMPlexGetChart(gatherDM,&pStart,&pEnd);CHKERRQ(ierr);
18076462276dSToby Isaac   numPoints = pEnd - pStart;
18086462276dSToby Isaac   ierr = MPI_Bcast(&numPoints,1,MPIU_INT,0,comm);CHKERRQ(ierr);
18096462276dSToby Isaac   ierr = PetscMalloc1(numPoints,&points);CHKERRQ(ierr);
18106462276dSToby Isaac   ierr = PetscSFCreate(comm,&migrationSF);CHKERRQ(ierr);
18116462276dSToby Isaac   for (p = 0; p < numPoints; p++) {
18126462276dSToby Isaac     points[p].index = p;
18136462276dSToby Isaac     points[p].rank  = 0;
18146462276dSToby Isaac   }
18156462276dSToby Isaac   ierr = PetscSFSetGraph(migrationSF,pEnd-pStart,numPoints,NULL,PETSC_OWN_POINTER,points,PETSC_OWN_POINTER);CHKERRQ(ierr);
18166462276dSToby Isaac   ierr = DMPlexCreate(comm, redundantMesh);CHKERRQ(ierr);
18176462276dSToby Isaac   ierr = PetscObjectSetName((PetscObject) *redundantMesh, "Redundant Mesh");CHKERRQ(ierr);
18186462276dSToby Isaac   ierr = DMPlexMigrate(gatherDM, migrationSF, *redundantMesh);CHKERRQ(ierr);
18196462276dSToby Isaac   ierr = DMPlexCreatePointSF(*redundantMesh, migrationSF, PETSC_FALSE, &sfPoint);CHKERRQ(ierr);
18206462276dSToby Isaac   ierr = DMSetPointSF(*redundantMesh, sfPoint);CHKERRQ(ierr);
18216462276dSToby Isaac   ierr = DMGetCoordinateDM(*redundantMesh, &dmCoord);CHKERRQ(ierr);
18226462276dSToby Isaac   if (dmCoord) {ierr = DMSetPointSF(dmCoord, sfPoint);CHKERRQ(ierr);}
18236462276dSToby Isaac   ierr = PetscSFDestroy(&sfPoint);CHKERRQ(ierr);
18246462276dSToby Isaac   ierr = PetscSFDestroy(&migrationSF);CHKERRQ(ierr);
18256462276dSToby Isaac   ierr = DMDestroy(&gatherDM);CHKERRQ(ierr);
18266462276dSToby Isaac   PetscFunctionReturn(0);
18276462276dSToby Isaac }
1828