xref: /petsc/src/dm/impls/plex/plexdistribute.c (revision 8b0b4c70077becf5cb5aa61295a890b450cc9c47)
170034214SMatthew G. Knepley #include <petsc-private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
270034214SMatthew G. Knepley #include <petscsf.h>
370034214SMatthew G. Knepley 
470034214SMatthew G. Knepley #undef __FUNCT__
570034214SMatthew G. Knepley #define __FUNCT__ "DMPlexSetAdjacencyUseCone"
670034214SMatthew G. Knepley /*@
770034214SMatthew G. Knepley   DMPlexSetAdjacencyUseCone - Define adjacency in the mesh using either the cone or the support first
870034214SMatthew G. Knepley 
970034214SMatthew G. Knepley   Input Parameters:
1070034214SMatthew G. Knepley + dm      - The DM object
1170034214SMatthew G. Knepley - useCone - Flag to use the cone first
1270034214SMatthew G. Knepley 
1370034214SMatthew G. Knepley   Level: intermediate
1470034214SMatthew G. Knepley 
1570034214SMatthew G. Knepley   Notes:
1670034214SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE
1770034214SMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in star(cone(p)),    useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
1870034214SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
1970034214SMatthew G. Knepley 
2070034214SMatthew G. Knepley .seealso: DMPlexGetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure(), DMPlexGetAdjacencyUseClosure(), DMPlexDistribute(), DMPlexPreallocateOperator()
2170034214SMatthew G. Knepley @*/
2270034214SMatthew G. Knepley PetscErrorCode DMPlexSetAdjacencyUseCone(DM dm, PetscBool useCone)
2370034214SMatthew G. Knepley {
2470034214SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *) dm->data;
2570034214SMatthew G. Knepley 
2670034214SMatthew G. Knepley   PetscFunctionBegin;
2770034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2870034214SMatthew G. Knepley   mesh->useCone = useCone;
2970034214SMatthew G. Knepley   PetscFunctionReturn(0);
3070034214SMatthew G. Knepley }
3170034214SMatthew G. Knepley 
3270034214SMatthew G. Knepley #undef __FUNCT__
3370034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacencyUseCone"
3470034214SMatthew G. Knepley /*@
3570034214SMatthew G. Knepley   DMPlexGetAdjacencyUseCone - Query whether adjacency in the mesh uses the cone or the support first
3670034214SMatthew G. Knepley 
3770034214SMatthew G. Knepley   Input Parameter:
3870034214SMatthew G. Knepley . dm      - The DM object
3970034214SMatthew G. Knepley 
4070034214SMatthew G. Knepley   Output Parameter:
4170034214SMatthew G. Knepley . useCone - Flag to use the cone first
4270034214SMatthew G. Knepley 
4370034214SMatthew G. Knepley   Level: intermediate
4470034214SMatthew G. Knepley 
4570034214SMatthew G. Knepley   Notes:
4670034214SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE
4770034214SMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in star(cone(p)),    useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
4870034214SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
4970034214SMatthew G. Knepley 
5070034214SMatthew G. Knepley .seealso: DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure(), DMPlexGetAdjacencyUseClosure(), DMPlexDistribute(), DMPlexPreallocateOperator()
5170034214SMatthew G. Knepley @*/
5270034214SMatthew G. Knepley PetscErrorCode DMPlexGetAdjacencyUseCone(DM dm, PetscBool *useCone)
5370034214SMatthew G. Knepley {
5470034214SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *) dm->data;
5570034214SMatthew G. Knepley 
5670034214SMatthew G. Knepley   PetscFunctionBegin;
5770034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5870034214SMatthew G. Knepley   PetscValidIntPointer(useCone, 2);
5970034214SMatthew G. Knepley   *useCone = mesh->useCone;
6070034214SMatthew G. Knepley   PetscFunctionReturn(0);
6170034214SMatthew G. Knepley }
6270034214SMatthew G. Knepley 
6370034214SMatthew G. Knepley #undef __FUNCT__
6470034214SMatthew G. Knepley #define __FUNCT__ "DMPlexSetAdjacencyUseClosure"
6570034214SMatthew G. Knepley /*@
6670034214SMatthew G. Knepley   DMPlexSetAdjacencyUseClosure - Define adjacency in the mesh using the transitive closure
6770034214SMatthew G. Knepley 
6870034214SMatthew G. Knepley   Input Parameters:
6970034214SMatthew G. Knepley + dm      - The DM object
7070034214SMatthew G. Knepley - useClosure - Flag to use the closure
7170034214SMatthew G. Knepley 
7270034214SMatthew G. Knepley   Level: intermediate
7370034214SMatthew G. Knepley 
7470034214SMatthew G. Knepley   Notes:
7570034214SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE
7670034214SMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in star(cone(p)),    useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
7770034214SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
7870034214SMatthew G. Knepley 
7970034214SMatthew G. Knepley .seealso: DMPlexGetAdjacencyUseClosure(), DMPlexSetAdjacencyUseCone(), DMPlexGetAdjacencyUseCone(), DMPlexDistribute(), DMPlexPreallocateOperator()
8070034214SMatthew G. Knepley @*/
8170034214SMatthew G. Knepley PetscErrorCode DMPlexSetAdjacencyUseClosure(DM dm, PetscBool useClosure)
8270034214SMatthew G. Knepley {
8370034214SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *) dm->data;
8470034214SMatthew G. Knepley 
8570034214SMatthew G. Knepley   PetscFunctionBegin;
8670034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8770034214SMatthew G. Knepley   mesh->useClosure = useClosure;
8870034214SMatthew G. Knepley   PetscFunctionReturn(0);
8970034214SMatthew G. Knepley }
9070034214SMatthew G. Knepley 
9170034214SMatthew G. Knepley #undef __FUNCT__
9270034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacencyUseClosure"
9370034214SMatthew G. Knepley /*@
9470034214SMatthew G. Knepley   DMPlexGetAdjacencyUseClosure - Query whether adjacency in the mesh uses the transitive closure
9570034214SMatthew G. Knepley 
9670034214SMatthew G. Knepley   Input Parameter:
9770034214SMatthew G. Knepley . dm      - The DM object
9870034214SMatthew G. Knepley 
9970034214SMatthew G. Knepley   Output Parameter:
10070034214SMatthew G. Knepley . useClosure - Flag to use the closure
10170034214SMatthew G. Knepley 
10270034214SMatthew G. Knepley   Level: intermediate
10370034214SMatthew G. Knepley 
10470034214SMatthew G. Knepley   Notes:
10570034214SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE
10670034214SMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in star(cone(p)),    useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
10770034214SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
10870034214SMatthew G. Knepley 
10970034214SMatthew G. Knepley .seealso: DMPlexSetAdjacencyUseClosure(), DMPlexSetAdjacencyUseCone(), DMPlexGetAdjacencyUseCone(), DMPlexDistribute(), DMPlexPreallocateOperator()
11070034214SMatthew G. Knepley @*/
11170034214SMatthew G. Knepley PetscErrorCode DMPlexGetAdjacencyUseClosure(DM dm, PetscBool *useClosure)
11270034214SMatthew G. Knepley {
11370034214SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *) dm->data;
11470034214SMatthew G. Knepley 
11570034214SMatthew G. Knepley   PetscFunctionBegin;
11670034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11770034214SMatthew G. Knepley   PetscValidIntPointer(useClosure, 2);
11870034214SMatthew G. Knepley   *useClosure = mesh->useClosure;
11970034214SMatthew G. Knepley   PetscFunctionReturn(0);
12070034214SMatthew G. Knepley }
12170034214SMatthew G. Knepley 
12270034214SMatthew G. Knepley #undef __FUNCT__
123*8b0b4c70SToby Isaac #define __FUNCT__ "DMPlexSetAdjacencyUseConstraints"
124*8b0b4c70SToby Isaac /*@
125*8b0b4c70SToby Isaac   DMPlexSetAdjacencyUseConstraints - Define adjacency in the mesh using the point-to-point constraints.
126*8b0b4c70SToby Isaac 
127*8b0b4c70SToby Isaac   Input Parameters:
128*8b0b4c70SToby Isaac + dm      - The DM object
129*8b0b4c70SToby Isaac - useConstraints - Flag to use the constraints.  If PETSC_TRUE, then constrained points are omitted from DMPlexGetAdjacency(), and their anchor points appear in their place.
130*8b0b4c70SToby Isaac 
131*8b0b4c70SToby Isaac   Level: intermediate
132*8b0b4c70SToby Isaac 
133*8b0b4c70SToby Isaac .seealso: DMPlexGetAdjacencyUseClosure(), DMPlexSetAdjacencyUseCone(), DMPlexGetAdjacencyUseCone(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexSetConstraints()
134*8b0b4c70SToby Isaac @*/
135*8b0b4c70SToby Isaac PetscErrorCode DMPlexSetAdjacencyUseConstraints(DM dm, PetscBool useConstraints)
136*8b0b4c70SToby Isaac {
137*8b0b4c70SToby Isaac   DM_Plex *mesh = (DM_Plex *) dm->data;
138*8b0b4c70SToby Isaac 
139*8b0b4c70SToby Isaac   PetscFunctionBegin;
140*8b0b4c70SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
141*8b0b4c70SToby Isaac   mesh->useConstraints = useConstraints;
142*8b0b4c70SToby Isaac   PetscFunctionReturn(0);
143*8b0b4c70SToby Isaac }
144*8b0b4c70SToby Isaac 
145*8b0b4c70SToby Isaac #undef __FUNCT__
146*8b0b4c70SToby Isaac #define __FUNCT__ "DMPlexGetAdjacencyUseConstraints"
147*8b0b4c70SToby Isaac /*@
148*8b0b4c70SToby Isaac   DMPlexGetAdjacencyUseConstraints - Query whether adjacency in the mesh uses the point-to-point constraints.
149*8b0b4c70SToby Isaac 
150*8b0b4c70SToby Isaac   Input Parameter:
151*8b0b4c70SToby Isaac . dm      - The DM object
152*8b0b4c70SToby Isaac 
153*8b0b4c70SToby Isaac   Output Parameter:
154*8b0b4c70SToby Isaac . useConstraints - Flag to use the closure.  If PETSC_TRUE, then constrained points are omitted from DMPlexGetAdjacency(), and their anchor points appear in their place.
155*8b0b4c70SToby Isaac 
156*8b0b4c70SToby Isaac   Level: intermediate
157*8b0b4c70SToby Isaac 
158*8b0b4c70SToby Isaac .seealso: DMPlexSetAdjacencyUseConstraints(), DMPlexSetAdjacencyUseCone(), DMPlexGetAdjacencyUseCone(), DMPlexDistribute(), DMPlexPreallocateOperator(), DMPlexSetConstraints()
159*8b0b4c70SToby Isaac @*/
160*8b0b4c70SToby Isaac PetscErrorCode DMPlexGetAdjacencyUseConstraints(DM dm, PetscBool *useConstraints)
161*8b0b4c70SToby Isaac {
162*8b0b4c70SToby Isaac   DM_Plex *mesh = (DM_Plex *) dm->data;
163*8b0b4c70SToby Isaac 
164*8b0b4c70SToby Isaac   PetscFunctionBegin;
165*8b0b4c70SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
166*8b0b4c70SToby Isaac   PetscValidIntPointer(useConstraints, 2);
167*8b0b4c70SToby Isaac   *useConstraints = mesh->useConstraints;
168*8b0b4c70SToby Isaac   PetscFunctionReturn(0);
169*8b0b4c70SToby Isaac }
170*8b0b4c70SToby Isaac 
171*8b0b4c70SToby Isaac #undef __FUNCT__
17270034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacency_Cone_Internal"
17370034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Cone_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[])
17470034214SMatthew G. Knepley {
17570034214SMatthew G. Knepley   const PetscInt *cone = NULL;
17670034214SMatthew G. Knepley   PetscInt        numAdj = 0, maxAdjSize = *adjSize, coneSize, c;
17770034214SMatthew G. Knepley   PetscErrorCode  ierr;
17870034214SMatthew G. Knepley 
17970034214SMatthew G. Knepley   PetscFunctionBeginHot;
18070034214SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
18170034214SMatthew G. Knepley   ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
18270034214SMatthew G. Knepley   for (c = 0; c < coneSize; ++c) {
18370034214SMatthew G. Knepley     const PetscInt *support = NULL;
18470034214SMatthew G. Knepley     PetscInt        supportSize, s, q;
18570034214SMatthew G. Knepley 
18670034214SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr);
18770034214SMatthew G. Knepley     ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr);
18870034214SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
18970034214SMatthew G. Knepley       for (q = 0; q < numAdj || (adj[numAdj++] = support[s],0); ++q) {
19070034214SMatthew G. Knepley         if (support[s] == adj[q]) break;
19170034214SMatthew G. Knepley       }
19270034214SMatthew G. Knepley       if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
19370034214SMatthew G. Knepley     }
19470034214SMatthew G. Knepley   }
19570034214SMatthew G. Knepley   *adjSize = numAdj;
19670034214SMatthew G. Knepley   PetscFunctionReturn(0);
19770034214SMatthew G. Knepley }
19870034214SMatthew G. Knepley 
19970034214SMatthew G. Knepley #undef __FUNCT__
20070034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacency_Support_Internal"
20170034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Support_Internal(DM dm, PetscInt p, PetscInt *adjSize, PetscInt adj[])
20270034214SMatthew G. Knepley {
20370034214SMatthew G. Knepley   const PetscInt *support = NULL;
20470034214SMatthew G. Knepley   PetscInt        numAdj   = 0, maxAdjSize = *adjSize, supportSize, s;
20570034214SMatthew G. Knepley   PetscErrorCode  ierr;
20670034214SMatthew G. Knepley 
20770034214SMatthew G. Knepley   PetscFunctionBeginHot;
20870034214SMatthew G. Knepley   ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
20970034214SMatthew G. Knepley   ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr);
21070034214SMatthew G. Knepley   for (s = 0; s < supportSize; ++s) {
21170034214SMatthew G. Knepley     const PetscInt *cone = NULL;
21270034214SMatthew G. Knepley     PetscInt        coneSize, c, q;
21370034214SMatthew G. Knepley 
21470034214SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
21570034214SMatthew G. Knepley     ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
21670034214SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
21770034214SMatthew G. Knepley       for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) {
21870034214SMatthew G. Knepley         if (cone[c] == adj[q]) break;
21970034214SMatthew G. Knepley       }
22070034214SMatthew G. Knepley       if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
22170034214SMatthew G. Knepley     }
22270034214SMatthew G. Knepley   }
22370034214SMatthew G. Knepley   *adjSize = numAdj;
22470034214SMatthew G. Knepley   PetscFunctionReturn(0);
22570034214SMatthew G. Knepley }
22670034214SMatthew G. Knepley 
22770034214SMatthew G. Knepley #undef __FUNCT__
22870034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacency_Transitive_Internal"
22970034214SMatthew G. Knepley static PetscErrorCode DMPlexGetAdjacency_Transitive_Internal(DM dm, PetscInt p, PetscBool useClosure, PetscInt *adjSize, PetscInt adj[])
23070034214SMatthew G. Knepley {
23170034214SMatthew G. Knepley   PetscInt      *star = NULL;
23270034214SMatthew G. Knepley   PetscInt       numAdj = 0, maxAdjSize = *adjSize, starSize, s;
23370034214SMatthew G. Knepley   PetscErrorCode ierr;
23470034214SMatthew G. Knepley 
23570034214SMatthew G. Knepley   PetscFunctionBeginHot;
23670034214SMatthew G. Knepley   ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, &star);CHKERRQ(ierr);
23770034214SMatthew G. Knepley   for (s = 0; s < starSize*2; s += 2) {
23870034214SMatthew G. Knepley     const PetscInt *closure = NULL;
23970034214SMatthew G. Knepley     PetscInt        closureSize, c, q;
24070034214SMatthew G. Knepley 
24170034214SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr);
24270034214SMatthew G. Knepley     for (c = 0; c < closureSize*2; c += 2) {
24370034214SMatthew G. Knepley       for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) {
24470034214SMatthew G. Knepley         if (closure[c] == adj[q]) break;
24570034214SMatthew G. Knepley       }
24670034214SMatthew G. Knepley       if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
24770034214SMatthew G. Knepley     }
24870034214SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt**) &closure);CHKERRQ(ierr);
24970034214SMatthew G. Knepley   }
25070034214SMatthew G. Knepley   ierr = DMPlexRestoreTransitiveClosure(dm, p, useClosure, &starSize, &star);CHKERRQ(ierr);
25170034214SMatthew G. Knepley   *adjSize = numAdj;
25270034214SMatthew G. Knepley   PetscFunctionReturn(0);
25370034214SMatthew G. Knepley }
25470034214SMatthew G. Knepley 
25570034214SMatthew G. Knepley #undef __FUNCT__
25670034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacency_Internal"
257*8b0b4c70SToby Isaac PetscErrorCode DMPlexGetAdjacency_Internal(DM dm, PetscInt p, PetscBool useCone, PetscBool useTransitiveClosure, PetscBool useConstraints, PetscInt *adjSize, PetscInt *adj[])
25870034214SMatthew G. Knepley {
25979bad331SMatthew G. Knepley   static PetscInt asiz = 0;
260*8b0b4c70SToby Isaac   PetscInt maxAnchors = 1;
261*8b0b4c70SToby Isaac   PetscInt aStart = -1, aEnd = -1;
262*8b0b4c70SToby Isaac   PetscInt maxAdjSize;
263*8b0b4c70SToby Isaac   PetscSection aSec = NULL;
264*8b0b4c70SToby Isaac   IS aIS = NULL;
265*8b0b4c70SToby Isaac   const PetscInt *anchors;
26670034214SMatthew G. Knepley   PetscErrorCode  ierr;
26770034214SMatthew G. Knepley 
26870034214SMatthew G. Knepley   PetscFunctionBeginHot;
269*8b0b4c70SToby Isaac   if (useConstraints) {
270*8b0b4c70SToby Isaac     ierr = DMPlexGetConstraints(dm,&aSec,&aIS);CHKERRQ(ierr);
271*8b0b4c70SToby Isaac     if (aSec) {
272*8b0b4c70SToby Isaac       ierr = PetscSectionGetMaxDof(aSec,&maxAnchors);CHKERRQ(ierr);
273*8b0b4c70SToby Isaac       ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr);
274*8b0b4c70SToby Isaac       ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr);
275*8b0b4c70SToby Isaac     }
276*8b0b4c70SToby Isaac   }
27779bad331SMatthew G. Knepley   if (!*adj) {
27879bad331SMatthew G. Knepley     PetscInt depth, maxConeSize, maxSupportSize;
27979bad331SMatthew G. Knepley 
28079bad331SMatthew G. Knepley     ierr  = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
28179bad331SMatthew G. Knepley     ierr  = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
28279bad331SMatthew G. Knepley     asiz  = PetscPowInt(maxConeSize, depth+1) * PetscPowInt(maxSupportSize, depth+1) + 1;
283*8b0b4c70SToby Isaac     asiz *= maxAnchors;
28479bad331SMatthew G. Knepley     ierr  = PetscMalloc1(asiz,adj);CHKERRQ(ierr);
28579bad331SMatthew G. Knepley   }
28679bad331SMatthew G. Knepley   if (*adjSize < 0) *adjSize = asiz;
287*8b0b4c70SToby Isaac   maxAdjSize = *adjSize;
28870034214SMatthew G. Knepley   if (useTransitiveClosure) {
28979bad331SMatthew G. Knepley     ierr = DMPlexGetAdjacency_Transitive_Internal(dm, p, useCone, adjSize, *adj);CHKERRQ(ierr);
29070034214SMatthew G. Knepley   } else if (useCone) {
29179bad331SMatthew G. Knepley     ierr = DMPlexGetAdjacency_Cone_Internal(dm, p, adjSize, *adj);CHKERRQ(ierr);
29270034214SMatthew G. Knepley   } else {
29379bad331SMatthew G. Knepley     ierr = DMPlexGetAdjacency_Support_Internal(dm, p, adjSize, *adj);CHKERRQ(ierr);
29470034214SMatthew G. Knepley   }
295*8b0b4c70SToby Isaac   if (useConstraints && aSec) {
296*8b0b4c70SToby Isaac     PetscInt origSize = *adjSize;
297*8b0b4c70SToby Isaac     PetscInt numAdj = origSize;
298*8b0b4c70SToby Isaac     PetscInt i = 0, j;
299*8b0b4c70SToby Isaac     PetscInt *orig = *adj;
300*8b0b4c70SToby Isaac 
301*8b0b4c70SToby Isaac     while (i < origSize) {
302*8b0b4c70SToby Isaac       PetscInt p = orig[i];
303*8b0b4c70SToby Isaac       PetscInt aDof = 0;
304*8b0b4c70SToby Isaac 
305*8b0b4c70SToby Isaac       if (p >= aStart && p < aEnd) {
306*8b0b4c70SToby Isaac         ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr);
307*8b0b4c70SToby Isaac       }
308*8b0b4c70SToby Isaac       if (aDof) {
309*8b0b4c70SToby Isaac         PetscInt aOff;
310*8b0b4c70SToby Isaac         PetscInt s, q;
311*8b0b4c70SToby Isaac 
312*8b0b4c70SToby Isaac         for (j = i + 1; j < numAdj; j++) {
313*8b0b4c70SToby Isaac           orig[j - 1] = orig[j];
314*8b0b4c70SToby Isaac         }
315*8b0b4c70SToby Isaac         origSize--;
316*8b0b4c70SToby Isaac         numAdj--;
317*8b0b4c70SToby Isaac         ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr);
318*8b0b4c70SToby Isaac         for (s = 0; s < aDof; ++s) {
319*8b0b4c70SToby Isaac           for (q = 0; q < numAdj || (orig[numAdj++] = anchors[aOff+s],0); ++q) {
320*8b0b4c70SToby Isaac             if (anchors[aOff+s] == orig[q]) break;
321*8b0b4c70SToby Isaac           }
322*8b0b4c70SToby Isaac           if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
323*8b0b4c70SToby Isaac         }
324*8b0b4c70SToby Isaac       }
325*8b0b4c70SToby Isaac       else {
326*8b0b4c70SToby Isaac         i++;
327*8b0b4c70SToby Isaac       }
328*8b0b4c70SToby Isaac     }
329*8b0b4c70SToby Isaac     *adjSize = numAdj;
330*8b0b4c70SToby Isaac     ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);
331*8b0b4c70SToby Isaac   }
33270034214SMatthew G. Knepley   PetscFunctionReturn(0);
33370034214SMatthew G. Knepley }
33470034214SMatthew G. Knepley 
33570034214SMatthew G. Knepley #undef __FUNCT__
33670034214SMatthew G. Knepley #define __FUNCT__ "DMPlexGetAdjacency"
33770034214SMatthew G. Knepley /*@
33870034214SMatthew G. Knepley   DMPlexGetAdjacency - Return all points adjacent to the given point
33970034214SMatthew G. Knepley 
34070034214SMatthew G. Knepley   Input Parameters:
34170034214SMatthew G. Knepley + dm - The DM object
34270034214SMatthew G. Knepley . p  - The point
34370034214SMatthew G. Knepley . adjSize - The maximum size of adj if it is non-NULL, or PETSC_DETERMINE
34470034214SMatthew G. Knepley - adj - Either NULL so that the array is allocated, or an existing array with size adjSize
34570034214SMatthew G. Knepley 
34670034214SMatthew G. Knepley   Output Parameters:
34770034214SMatthew G. Knepley + adjSize - The number of adjacent points
34870034214SMatthew G. Knepley - adj - The adjacent points
34970034214SMatthew G. Knepley 
35070034214SMatthew G. Knepley   Level: advanced
35170034214SMatthew G. Knepley 
35270034214SMatthew G. Knepley   Notes: The user must PetscFree the adj array if it was not passed in.
35370034214SMatthew G. Knepley 
35470034214SMatthew G. Knepley .seealso: DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure(), DMPlexDistribute(), DMCreateMatrix(), DMPlexPreallocateOperator()
35570034214SMatthew G. Knepley @*/
35670034214SMatthew G. Knepley PetscErrorCode DMPlexGetAdjacency(DM dm, PetscInt p, PetscInt *adjSize, PetscInt *adj[])
35770034214SMatthew G. Knepley {
35870034214SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex *) dm->data;
35970034214SMatthew G. Knepley   PetscErrorCode ierr;
36070034214SMatthew G. Knepley 
36170034214SMatthew G. Knepley   PetscFunctionBeginHot;
36270034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36370034214SMatthew G. Knepley   PetscValidPointer(adjSize,3);
36470034214SMatthew G. Knepley   PetscValidPointer(adj,4);
365*8b0b4c70SToby Isaac   ierr = DMPlexGetAdjacency_Internal(dm, p, mesh->useCone, mesh->useClosure, mesh->useConstraints, adjSize, adj);CHKERRQ(ierr);
36670034214SMatthew G. Knepley   PetscFunctionReturn(0);
36770034214SMatthew G. Knepley }
36870034214SMatthew G. Knepley 
36970034214SMatthew G. Knepley #undef __FUNCT__
37070034214SMatthew G. Knepley #define __FUNCT__ "DMPlexDistributeField"
37170034214SMatthew G. Knepley /*@
37270034214SMatthew G. Knepley   DMPlexDistributeField - Distribute field data to match a given PetscSF, usually the SF from mesh distribution
37370034214SMatthew G. Knepley 
37470034214SMatthew G. Knepley   Collective on DM
37570034214SMatthew G. Knepley 
37670034214SMatthew G. Knepley   Input Parameters:
37770034214SMatthew G. Knepley + dm - The DMPlex object
37870034214SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern
37970034214SMatthew G. Knepley . originalSection - The PetscSection for existing data layout
38070034214SMatthew G. Knepley - originalVec - The existing data
38170034214SMatthew G. Knepley 
38270034214SMatthew G. Knepley   Output Parameters:
38370034214SMatthew G. Knepley + newSection - The PetscSF describing the new data layout
38470034214SMatthew G. Knepley - newVec - The new data
38570034214SMatthew G. Knepley 
38670034214SMatthew G. Knepley   Level: developer
38770034214SMatthew G. Knepley 
38870034214SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeData()
38970034214SMatthew G. Knepley @*/
39070034214SMatthew G. Knepley PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec)
39170034214SMatthew G. Knepley {
39270034214SMatthew G. Knepley   PetscSF        fieldSF;
39370034214SMatthew G. Knepley   PetscInt      *remoteOffsets, fieldSize;
39470034214SMatthew G. Knepley   PetscScalar   *originalValues, *newValues;
39570034214SMatthew G. Knepley   PetscErrorCode ierr;
39670034214SMatthew G. Knepley 
39770034214SMatthew G. Knepley   PetscFunctionBegin;
39870034214SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_DistributeField,dm,0,0,0);CHKERRQ(ierr);
39970034214SMatthew G. Knepley   ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr);
40070034214SMatthew G. Knepley 
40170034214SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr);
40270034214SMatthew G. Knepley   ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr);
40370034214SMatthew G. Knepley   ierr = VecSetType(newVec,dm->vectype);CHKERRQ(ierr);
40470034214SMatthew G. Knepley 
40570034214SMatthew G. Knepley   ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr);
40670034214SMatthew G. Knepley   ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr);
40770034214SMatthew G. Knepley   ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr);
40870034214SMatthew G. Knepley   ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr);
40970034214SMatthew G. Knepley   ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr);
41070034214SMatthew G. Knepley   ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr);
41170034214SMatthew G. Knepley   ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr);
41270034214SMatthew G. Knepley   ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr);
41370034214SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_DistributeField,dm,0,0,0);CHKERRQ(ierr);
41470034214SMatthew G. Knepley   PetscFunctionReturn(0);
41570034214SMatthew G. Knepley }
41670034214SMatthew G. Knepley 
41770034214SMatthew G. Knepley #undef __FUNCT__
41870034214SMatthew G. Knepley #define __FUNCT__ "DMPlexDistributeData"
41970034214SMatthew G. Knepley /*@
42070034214SMatthew G. Knepley   DMPlexDistributeData - Distribute field data to match a given PetscSF, usually the SF from mesh distribution
42170034214SMatthew G. Knepley 
42270034214SMatthew G. Knepley   Collective on DM
42370034214SMatthew G. Knepley 
42470034214SMatthew G. Knepley   Input Parameters:
42570034214SMatthew G. Knepley + dm - The DMPlex object
42670034214SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern
42770034214SMatthew G. Knepley . originalSection - The PetscSection for existing data layout
42870034214SMatthew G. Knepley . datatype - The type of data
42970034214SMatthew G. Knepley - originalData - The existing data
43070034214SMatthew G. Knepley 
43170034214SMatthew G. Knepley   Output Parameters:
43270034214SMatthew G. Knepley + newSection - The PetscSF describing the new data layout
43370034214SMatthew G. Knepley - newData - The new data
43470034214SMatthew G. Knepley 
43570034214SMatthew G. Knepley   Level: developer
43670034214SMatthew G. Knepley 
43770034214SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField()
43870034214SMatthew G. Knepley @*/
43970034214SMatthew G. Knepley PetscErrorCode DMPlexDistributeData(DM dm, PetscSF pointSF, PetscSection originalSection, MPI_Datatype datatype, void *originalData, PetscSection newSection, void **newData)
44070034214SMatthew G. Knepley {
44170034214SMatthew G. Knepley   PetscSF        fieldSF;
44270034214SMatthew G. Knepley   PetscInt      *remoteOffsets, fieldSize;
44370034214SMatthew G. Knepley   PetscMPIInt    dataSize;
44470034214SMatthew G. Knepley   PetscErrorCode ierr;
44570034214SMatthew G. Knepley 
44670034214SMatthew G. Knepley   PetscFunctionBegin;
44770034214SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_DistributeData,dm,0,0,0);CHKERRQ(ierr);
44870034214SMatthew G. Knepley   ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr);
44970034214SMatthew G. Knepley 
45070034214SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr);
45170034214SMatthew G. Knepley   ierr = MPI_Type_size(datatype, &dataSize);CHKERRQ(ierr);
45270034214SMatthew G. Knepley   ierr = PetscMalloc(fieldSize * dataSize, newData);CHKERRQ(ierr);
45370034214SMatthew G. Knepley 
45470034214SMatthew G. Knepley   ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr);
45570034214SMatthew G. Knepley   ierr = PetscSFBcastBegin(fieldSF, datatype, originalData, *newData);CHKERRQ(ierr);
45670034214SMatthew G. Knepley   ierr = PetscSFBcastEnd(fieldSF, datatype, originalData, *newData);CHKERRQ(ierr);
45770034214SMatthew G. Knepley   ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr);
45870034214SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_DistributeData,dm,0,0,0);CHKERRQ(ierr);
45970034214SMatthew G. Knepley   PetscFunctionReturn(0);
46070034214SMatthew G. Knepley }
46170034214SMatthew G. Knepley 
46270034214SMatthew G. Knepley #undef __FUNCT__
46370034214SMatthew G. Knepley #define __FUNCT__ "DMPlexDistribute"
46470034214SMatthew G. Knepley /*@C
46570034214SMatthew G. Knepley   DMPlexDistribute - Distributes the mesh and any associated sections.
46670034214SMatthew G. Knepley 
46770034214SMatthew G. Knepley   Not Collective
46870034214SMatthew G. Knepley 
46970034214SMatthew G. Knepley   Input Parameter:
47070034214SMatthew G. Knepley + dm  - The original DMPlex object
47170034214SMatthew G. Knepley . partitioner - The partitioning package, or NULL for the default
47270034214SMatthew G. Knepley - overlap - The overlap of partitions, 0 is the default
47370034214SMatthew G. Knepley 
47470034214SMatthew G. Knepley   Output Parameter:
47570034214SMatthew G. Knepley + sf - The PetscSF used for point distribution
47670034214SMatthew G. Knepley - parallelMesh - The distributed DMPlex object, or NULL
47770034214SMatthew G. Knepley 
478a9c22940SMatthew G. Knepley   Note: If the mesh was not distributed, the return value is NULL.
479a9c22940SMatthew G. Knepley 
480a9c22940SMatthew G. Knepley   The user can control the definition of adjacency for the mesh using DMPlexGetAdjacencyUseCone() and
481a9c22940SMatthew G. Knepley   DMPlexSetAdjacencyUseClosure(). They should choose the combination appropriate for the function
482a9c22940SMatthew G. Knepley   representation on the mesh.
48370034214SMatthew G. Knepley 
48470034214SMatthew G. Knepley   Level: intermediate
48570034214SMatthew G. Knepley 
48670034214SMatthew G. Knepley .keywords: mesh, elements
487a9c22940SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexDistributeByFace(), DMPlexSetAdjacencyUseCone(), DMPlexSetAdjacencyUseClosure()
48870034214SMatthew G. Knepley @*/
48970034214SMatthew G. Knepley PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, PetscSF *sf, DM *dmParallel)
49070034214SMatthew G. Knepley {
49170034214SMatthew G. Knepley   DM_Plex               *mesh   = (DM_Plex*) dm->data, *pmesh;
49270034214SMatthew G. Knepley   MPI_Comm               comm;
49370034214SMatthew G. Knepley   const PetscInt         height = 0;
49470034214SMatthew G. Knepley   PetscInt               dim, numRemoteRanks;
49570034214SMatthew G. Knepley   IS                     origCellPart,        origPart,        cellPart,        part;
49670034214SMatthew G. Knepley   PetscSection           origCellPartSection, origPartSection, cellPartSection, partSection;
49770034214SMatthew G. Knepley   PetscSFNode           *remoteRanks;
49870034214SMatthew G. Knepley   PetscSF                partSF, pointSF, coneSF;
49970034214SMatthew G. Knepley   ISLocalToGlobalMapping renumbering;
50070034214SMatthew G. Knepley   PetscSection           originalConeSection, newConeSection;
50170034214SMatthew G. Knepley   PetscInt              *remoteOffsets;
50270034214SMatthew G. Knepley   PetscInt              *cones, *newCones, newConesSize;
50370034214SMatthew G. Knepley   PetscBool              flg;
50470034214SMatthew G. Knepley   PetscMPIInt            rank, numProcs, p;
50570034214SMatthew G. Knepley   PetscErrorCode         ierr;
50670034214SMatthew G. Knepley 
50770034214SMatthew G. Knepley   PetscFunctionBegin;
50870034214SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50970034214SMatthew G. Knepley   if (sf) PetscValidPointer(sf,4);
51070034214SMatthew G. Knepley   PetscValidPointer(dmParallel,5);
51170034214SMatthew G. Knepley 
51270034214SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr);
51370034214SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
51470034214SMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
51570034214SMatthew G. Knepley   ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr);
51670034214SMatthew G. Knepley 
51770034214SMatthew G. Knepley   *dmParallel = NULL;
51870034214SMatthew G. Knepley   if (numProcs == 1) PetscFunctionReturn(0);
51970034214SMatthew G. Knepley 
520c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
52170034214SMatthew G. Knepley   /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */
52270034214SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_Partition,dm,0,0,0);CHKERRQ(ierr);
52370034214SMatthew G. Knepley   if (overlap > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Overlap > 1 not yet implemented");
52470034214SMatthew G. Knepley   ierr = DMPlexCreatePartition(dm, partitioner, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr);
52570034214SMatthew G. Knepley   /* Create SF assuming a serial partition for all processes: Could check for IS length here */
52670034214SMatthew G. Knepley   if (!rank) numRemoteRanks = numProcs;
52770034214SMatthew G. Knepley   else       numRemoteRanks = 0;
52870034214SMatthew G. Knepley   ierr = PetscMalloc1(numRemoteRanks, &remoteRanks);CHKERRQ(ierr);
52970034214SMatthew G. Knepley   for (p = 0; p < numRemoteRanks; ++p) {
53070034214SMatthew G. Knepley     remoteRanks[p].rank  = p;
53170034214SMatthew G. Knepley     remoteRanks[p].index = 0;
53270034214SMatthew G. Knepley   }
53370034214SMatthew G. Knepley   ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr);
53470034214SMatthew G. Knepley   ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr);
53570034214SMatthew G. Knepley   ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr);
53670034214SMatthew G. Knepley   if (flg) {
53770034214SMatthew G. Knepley     ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr);
53870034214SMatthew G. Knepley     ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
53970034214SMatthew G. Knepley     ierr = ISView(cellPart, NULL);CHKERRQ(ierr);
54070034214SMatthew G. Knepley     if (origCellPart) {
54170034214SMatthew G. Knepley       ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr);
54270034214SMatthew G. Knepley       ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
54370034214SMatthew G. Knepley       ierr = ISView(origCellPart, NULL);CHKERRQ(ierr);
54470034214SMatthew G. Knepley     }
54570034214SMatthew G. Knepley     ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr);
54670034214SMatthew G. Knepley   }
54770034214SMatthew G. Knepley   /* Close the partition over the mesh */
54870034214SMatthew G. Knepley   ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr);
54970034214SMatthew G. Knepley   ierr = ISDestroy(&cellPart);CHKERRQ(ierr);
55070034214SMatthew G. Knepley   ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr);
55170034214SMatthew G. Knepley   /* Create new mesh */
55270034214SMatthew G. Knepley   ierr  = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr);
553c73cfb54SMatthew G. Knepley   ierr  = DMSetDimension(*dmParallel, dim);CHKERRQ(ierr);
55470034214SMatthew G. Knepley   ierr  = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr);
55570034214SMatthew G. Knepley   pmesh = (DM_Plex*) (*dmParallel)->data;
55670034214SMatthew G. Knepley   /* Distribute sieve points and the global point numbering (replaces creating remote bases) */
55770034214SMatthew G. Knepley   ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr);
55870034214SMatthew G. Knepley   if (flg) {
55970034214SMatthew G. Knepley     ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr);
56070034214SMatthew G. Knepley     ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
56170034214SMatthew G. Knepley     ierr = ISView(part, NULL);CHKERRQ(ierr);
56270034214SMatthew G. Knepley     ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr);
56370034214SMatthew G. Knepley     ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr);
56470034214SMatthew G. Knepley     ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr);
56570034214SMatthew G. Knepley   }
56670034214SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_Partition,dm,0,0,0);CHKERRQ(ierr);
56770034214SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_DistributeCones,dm,0,0,0);CHKERRQ(ierr);
56870034214SMatthew G. Knepley   /* Distribute cone section */
56970034214SMatthew G. Knepley   ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr);
57070034214SMatthew G. Knepley   ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr);
57170034214SMatthew G. Knepley   ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr);
57270034214SMatthew G. Knepley   ierr = DMSetUp(*dmParallel);CHKERRQ(ierr);
57370034214SMatthew G. Knepley   {
57470034214SMatthew G. Knepley     PetscInt pStart, pEnd, p;
57570034214SMatthew G. Knepley 
57670034214SMatthew G. Knepley     ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr);
57770034214SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
57870034214SMatthew G. Knepley       PetscInt coneSize;
57970034214SMatthew G. Knepley       ierr               = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr);
58070034214SMatthew G. Knepley       pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize);
58170034214SMatthew G. Knepley     }
58270034214SMatthew G. Knepley   }
58370034214SMatthew G. Knepley   /* Communicate and renumber cones */
58470034214SMatthew G. Knepley   ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr);
58570034214SMatthew G. Knepley   ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr);
58670034214SMatthew G. Knepley   ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr);
58770034214SMatthew G. Knepley   ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
58870034214SMatthew G. Knepley   ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
58970034214SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr);
5909d90f715SBarry Smith   ierr = ISGlobalToLocalMappingApplyBlock(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr);
59170034214SMatthew G. Knepley   ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr);
59270034214SMatthew G. Knepley   if (flg) {
59370034214SMatthew G. Knepley     ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr);
59470034214SMatthew G. Knepley     ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
59570034214SMatthew G. Knepley     ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr);
59670034214SMatthew G. Knepley     ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
59770034214SMatthew G. Knepley     ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr);
59870034214SMatthew G. Knepley   }
59970034214SMatthew G. Knepley   ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr);
60070034214SMatthew G. Knepley   ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr);
60170034214SMatthew G. Knepley   ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
60270034214SMatthew G. Knepley   ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
60370034214SMatthew G. Knepley   ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr);
60470034214SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_DistributeCones,dm,0,0,0);CHKERRQ(ierr);
60570034214SMatthew G. Knepley   /* Create supports and stratify sieve */
60670034214SMatthew G. Knepley   {
60770034214SMatthew G. Knepley     PetscInt pStart, pEnd;
60870034214SMatthew G. Knepley 
60970034214SMatthew G. Knepley     ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
61070034214SMatthew G. Knepley     ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr);
61170034214SMatthew G. Knepley   }
61270034214SMatthew G. Knepley   ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr);
61370034214SMatthew G. Knepley   ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr);
61470034214SMatthew G. Knepley   /* Create point SF for parallel mesh */
61570034214SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_DistributeSF,dm,0,0,0);CHKERRQ(ierr);
61670034214SMatthew G. Knepley   {
61770034214SMatthew G. Knepley     const PetscInt *leaves;
61870034214SMatthew G. Knepley     PetscSFNode    *remotePoints, *rowners, *lowners;
61970034214SMatthew G. Knepley     PetscInt        numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints;
62070034214SMatthew G. Knepley     PetscInt        pStart, pEnd;
62170034214SMatthew G. Knepley 
62270034214SMatthew G. Knepley     ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr);
62370034214SMatthew G. Knepley     ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr);
62470034214SMatthew G. Knepley     ierr = PetscMalloc2(numRoots,&rowners,numLeaves,&lowners);CHKERRQ(ierr);
62570034214SMatthew G. Knepley     for (p=0; p<numRoots; p++) {
62670034214SMatthew G. Knepley       rowners[p].rank  = -1;
62770034214SMatthew G. Knepley       rowners[p].index = -1;
62870034214SMatthew G. Knepley     }
62970034214SMatthew G. Knepley     if (origCellPart) {
63070034214SMatthew G. Knepley       /* Make sure points in the original partition are not assigned to other procs */
63170034214SMatthew G. Knepley       const PetscInt *origPoints;
63270034214SMatthew G. Knepley 
63370034214SMatthew G. Knepley       ierr = DMPlexCreatePartitionClosure(dm, origCellPartSection, origCellPart, &origPartSection, &origPart);CHKERRQ(ierr);
63470034214SMatthew G. Knepley       ierr = ISGetIndices(origPart, &origPoints);CHKERRQ(ierr);
63570034214SMatthew G. Knepley       for (p = 0; p < numProcs; ++p) {
63670034214SMatthew G. Knepley         PetscInt dof, off, d;
63770034214SMatthew G. Knepley 
63870034214SMatthew G. Knepley         ierr = PetscSectionGetDof(origPartSection, p, &dof);CHKERRQ(ierr);
63970034214SMatthew G. Knepley         ierr = PetscSectionGetOffset(origPartSection, p, &off);CHKERRQ(ierr);
64070034214SMatthew G. Knepley         for (d = off; d < off+dof; ++d) {
64170034214SMatthew G. Knepley           rowners[origPoints[d]].rank = p;
64270034214SMatthew G. Knepley         }
64370034214SMatthew G. Knepley       }
64470034214SMatthew G. Knepley       ierr = ISRestoreIndices(origPart, &origPoints);CHKERRQ(ierr);
64570034214SMatthew G. Knepley       ierr = ISDestroy(&origPart);CHKERRQ(ierr);
64670034214SMatthew G. Knepley       ierr = PetscSectionDestroy(&origPartSection);CHKERRQ(ierr);
64770034214SMatthew G. Knepley     }
64870034214SMatthew G. Knepley     ierr = ISDestroy(&origCellPart);CHKERRQ(ierr);
64970034214SMatthew G. Knepley     ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr);
65070034214SMatthew G. Knepley 
65170034214SMatthew G. Knepley     ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
65270034214SMatthew G. Knepley     ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
65370034214SMatthew G. Knepley     for (p = 0; p < numLeaves; ++p) {
65470034214SMatthew G. Knepley       if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */
65570034214SMatthew G. Knepley         lowners[p].rank  = rank;
65670034214SMatthew G. Knepley         lowners[p].index = leaves ? leaves[p] : p;
65770034214SMatthew G. Knepley       } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */
65870034214SMatthew G. Knepley         lowners[p].rank  = -2;
65970034214SMatthew G. Knepley         lowners[p].index = -2;
66070034214SMatthew G. Knepley       }
66170034214SMatthew G. Knepley     }
66270034214SMatthew G. Knepley     for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */
66370034214SMatthew G. Knepley       rowners[p].rank  = -3;
66470034214SMatthew G. Knepley       rowners[p].index = -3;
66570034214SMatthew G. Knepley     }
66670034214SMatthew G. Knepley     ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr);
66770034214SMatthew G. Knepley     ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr);
66870034214SMatthew G. Knepley     ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
66970034214SMatthew G. Knepley     ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
67070034214SMatthew G. Knepley     for (p = 0; p < numLeaves; ++p) {
67170034214SMatthew G. Knepley       if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed");
67270034214SMatthew G. Knepley       if (lowners[p].rank != rank) ++numGhostPoints;
67370034214SMatthew G. Knepley     }
67470034214SMatthew G. Knepley     ierr = PetscMalloc1(numGhostPoints,    &ghostPoints);CHKERRQ(ierr);
67570034214SMatthew G. Knepley     ierr = PetscMalloc1(numGhostPoints, &remotePoints);CHKERRQ(ierr);
67670034214SMatthew G. Knepley     for (p = 0, gp = 0; p < numLeaves; ++p) {
67770034214SMatthew G. Knepley       if (lowners[p].rank != rank) {
67870034214SMatthew G. Knepley         ghostPoints[gp]        = leaves ? leaves[p] : p;
67970034214SMatthew G. Knepley         remotePoints[gp].rank  = lowners[p].rank;
68070034214SMatthew G. Knepley         remotePoints[gp].index = lowners[p].index;
68170034214SMatthew G. Knepley         ++gp;
68270034214SMatthew G. Knepley       }
68370034214SMatthew G. Knepley     }
68470034214SMatthew G. Knepley     ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr);
68570034214SMatthew G. Knepley     ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
68670034214SMatthew G. Knepley     ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr);
68770034214SMatthew G. Knepley   }
688a42b08eeSMatthew G. Knepley   pmesh->useCone    = mesh->useCone;
689a42b08eeSMatthew G. Knepley   pmesh->useClosure = mesh->useClosure;
69070034214SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_DistributeSF,dm,0,0,0);CHKERRQ(ierr);
691bf5244c7SMatthew G. Knepley   /* Distribute Coordinates */
692bf5244c7SMatthew G. Knepley   {
693bf5244c7SMatthew G. Knepley     PetscSection     originalCoordSection, newCoordSection;
694bf5244c7SMatthew G. Knepley     Vec              originalCoordinates, newCoordinates;
695bf5244c7SMatthew G. Knepley     PetscInt         bs;
696bf5244c7SMatthew G. Knepley     const char      *name;
697bf5244c7SMatthew G. Knepley     const PetscReal *maxCell, *L;
698bf5244c7SMatthew G. Knepley 
699bf5244c7SMatthew G. Knepley     ierr = DMGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr);
700bf5244c7SMatthew G. Knepley     ierr = DMGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr);
701bf5244c7SMatthew G. Knepley     ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr);
702bf5244c7SMatthew G. Knepley     ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr);
703bf5244c7SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr);
704bf5244c7SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr);
705bf5244c7SMatthew G. Knepley 
706bf5244c7SMatthew G. Knepley     ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr);
707bf5244c7SMatthew G. Knepley     ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr);
708bf5244c7SMatthew G. Knepley     ierr = VecGetBlockSize(originalCoordinates, &bs);CHKERRQ(ierr);
709bf5244c7SMatthew G. Knepley     ierr = VecSetBlockSize(newCoordinates, bs);CHKERRQ(ierr);
710bf5244c7SMatthew G. Knepley     ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr);
711bf5244c7SMatthew G. Knepley     ierr = DMGetPeriodicity(dm, &maxCell, &L);CHKERRQ(ierr);
712bf5244c7SMatthew G. Knepley     if (L) {ierr = DMSetPeriodicity(*dmParallel, maxCell, L);CHKERRQ(ierr);}
713bf5244c7SMatthew G. Knepley   }
714bf5244c7SMatthew G. Knepley   /* Distribute labels */
715bf5244c7SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_DistributeLabels,dm,0,0,0);CHKERRQ(ierr);
716bf5244c7SMatthew G. Knepley   {
717bf5244c7SMatthew G. Knepley     DMLabel  next      = mesh->labels, newNext = pmesh->labels;
718bf5244c7SMatthew G. Knepley     PetscInt numLabels = 0, l;
719bf5244c7SMatthew G. Knepley 
720bf5244c7SMatthew G. Knepley     /* Bcast number of labels */
721bf5244c7SMatthew G. Knepley     while (next) {++numLabels; next = next->next;}
722bf5244c7SMatthew G. Knepley     ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
723bf5244c7SMatthew G. Knepley     next = mesh->labels;
724bf5244c7SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
725bf5244c7SMatthew G. Knepley       DMLabel   labelNew;
726bf5244c7SMatthew G. Knepley       PetscBool isdepth;
727bf5244c7SMatthew G. Knepley 
728bf5244c7SMatthew G. Knepley       /* Skip "depth" because it is recreated */
729bf5244c7SMatthew G. Knepley       if (!rank) {ierr = PetscStrcmp(next->name, "depth", &isdepth);CHKERRQ(ierr);}
730bf5244c7SMatthew G. Knepley       ierr = MPI_Bcast(&isdepth, 1, MPIU_BOOL, 0, comm);CHKERRQ(ierr);
731bf5244c7SMatthew G. Knepley       if (isdepth) {if (!rank) next = next->next; continue;}
732bf5244c7SMatthew G. Knepley       ierr = DMLabelDistribute(next, partSection, part, renumbering, &labelNew);CHKERRQ(ierr);
733bf5244c7SMatthew G. Knepley       /* Insert into list */
734bf5244c7SMatthew G. Knepley       if (newNext) newNext->next = labelNew;
735bf5244c7SMatthew G. Knepley       else         pmesh->labels = labelNew;
736bf5244c7SMatthew G. Knepley       newNext = labelNew;
737bf5244c7SMatthew G. Knepley       if (!rank) next = next->next;
738bf5244c7SMatthew G. Knepley     }
739bf5244c7SMatthew G. Knepley   }
740bf5244c7SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_DistributeLabels,dm,0,0,0);CHKERRQ(ierr);
741bf5244c7SMatthew G. Knepley   /* Setup hybrid structure */
742bf5244c7SMatthew G. Knepley   {
743bf5244c7SMatthew G. Knepley     const PetscInt *gpoints;
744bf5244c7SMatthew G. Knepley     PetscInt        depth, n, d;
745bf5244c7SMatthew G. Knepley 
746bf5244c7SMatthew G. Knepley     for (d = 0; d <= dim; ++d) {pmesh->hybridPointMax[d] = mesh->hybridPointMax[d];}
747bf5244c7SMatthew G. Knepley     ierr = MPI_Bcast(pmesh->hybridPointMax, dim+1, MPIU_INT, 0, comm);CHKERRQ(ierr);
748bf5244c7SMatthew G. Knepley     ierr = ISLocalToGlobalMappingGetSize(renumbering, &n);CHKERRQ(ierr);
749bf5244c7SMatthew G. Knepley     ierr = ISLocalToGlobalMappingGetIndices(renumbering, &gpoints);CHKERRQ(ierr);
750bf5244c7SMatthew G. Knepley     ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
751bf5244c7SMatthew G. Knepley     for (d = 0; d <= dim; ++d) {
752bf5244c7SMatthew G. Knepley       PetscInt pmax = pmesh->hybridPointMax[d], newmax = 0, pEnd, stratum[2], p;
753bf5244c7SMatthew G. Knepley 
754bf5244c7SMatthew G. Knepley       if (pmax < 0) continue;
755bf5244c7SMatthew G. Knepley       ierr = DMPlexGetDepthStratum(dm, d > depth ? depth : d, &stratum[0], &stratum[1]);CHKERRQ(ierr);
756bf5244c7SMatthew G. Knepley       ierr = DMPlexGetDepthStratum(*dmParallel, d, NULL, &pEnd);CHKERRQ(ierr);
757bf5244c7SMatthew G. Knepley       ierr = MPI_Bcast(stratum, 2, MPIU_INT, 0, comm);CHKERRQ(ierr);
758bf5244c7SMatthew G. Knepley       for (p = 0; p < n; ++p) {
759bf5244c7SMatthew G. Knepley         const PetscInt point = gpoints[p];
760bf5244c7SMatthew G. Knepley 
761bf5244c7SMatthew G. Knepley         if ((point >= stratum[0]) && (point < stratum[1]) && (point >= pmax)) ++newmax;
762bf5244c7SMatthew G. Knepley       }
763bf5244c7SMatthew G. Knepley       if (newmax > 0) pmesh->hybridPointMax[d] = pEnd - newmax;
764bf5244c7SMatthew G. Knepley       else            pmesh->hybridPointMax[d] = -1;
765bf5244c7SMatthew G. Knepley     }
766bf5244c7SMatthew G. Knepley     ierr = ISLocalToGlobalMappingRestoreIndices(renumbering, &gpoints);CHKERRQ(ierr);
767bf5244c7SMatthew G. Knepley   }
768bf5244c7SMatthew G. Knepley   /* Cleanup Partition */
769bf5244c7SMatthew G. Knepley   ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr);
770bf5244c7SMatthew G. Knepley   ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr);
771bf5244c7SMatthew G. Knepley   ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr);
772bf5244c7SMatthew G. Knepley   ierr = ISDestroy(&part);CHKERRQ(ierr);
77386719b60SMatthew G. Knepley   /* Copy BC */
77486719b60SMatthew G. Knepley   ierr = DMPlexCopyBoundary(dm, *dmParallel);CHKERRQ(ierr);
77570034214SMatthew G. Knepley   /* Cleanup */
77670034214SMatthew G. Knepley   if (sf) {*sf = pointSF;}
77770034214SMatthew G. Knepley   else    {ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr);}
77870034214SMatthew G. Knepley   ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr);
77970034214SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr);
78070034214SMatthew G. Knepley   PetscFunctionReturn(0);
78170034214SMatthew G. Knepley }
782