xref: /petsc/src/dm/impls/plex/plextree.c (revision 46bdb399d94e12811c9b8c1f2d0c6f1426397b77)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2d6a7ad0dSToby Isaac #include <../src/sys/utils/hash.h>
3af0996ceSBarry Smith #include <petsc/private/isimpl.h>
4af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h>
5d6a7ad0dSToby Isaac #include <petscsf.h>
60c37af3bSToby Isaac #include <petscds.h>
7d6a7ad0dSToby Isaac 
8d6a7ad0dSToby Isaac /** hierarchy routines */
9d6a7ad0dSToby Isaac 
10d6a7ad0dSToby Isaac #undef __FUNCT__
11d6a7ad0dSToby Isaac #define __FUNCT__ "DMPlexSetReferenceTree"
12d6a7ad0dSToby Isaac /*@
13d6a7ad0dSToby Isaac   DMPlexSetReferenceTree - set the reference tree for hierarchically non-conforming meshes.
14d6a7ad0dSToby Isaac 
15d6a7ad0dSToby Isaac   Not collective
16d6a7ad0dSToby Isaac 
17d6a7ad0dSToby Isaac   Input Parameters:
18d6a7ad0dSToby Isaac + dm - The DMPlex object
19d6a7ad0dSToby Isaac - ref - The reference tree DMPlex object
20d6a7ad0dSToby Isaac 
210b7167a0SToby Isaac   Level: intermediate
22d6a7ad0dSToby Isaac 
23da43764aSToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexCreateDefaultReferenceTree()
24d6a7ad0dSToby Isaac @*/
25d6a7ad0dSToby Isaac PetscErrorCode DMPlexSetReferenceTree(DM dm, DM ref)
26d6a7ad0dSToby Isaac {
27d6a7ad0dSToby Isaac   DM_Plex        *mesh = (DM_Plex *)dm->data;
28d6a7ad0dSToby Isaac   PetscErrorCode  ierr;
29d6a7ad0dSToby Isaac 
30d6a7ad0dSToby Isaac   PetscFunctionBegin;
31d6a7ad0dSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3247a1df27SMatthew G. Knepley   if (ref) {PetscValidHeaderSpecific(ref, DM_CLASSID, 2);}
33d6a7ad0dSToby Isaac   ierr = PetscObjectReference((PetscObject)ref);CHKERRQ(ierr);
34d6a7ad0dSToby Isaac   ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr);
35d6a7ad0dSToby Isaac   mesh->referenceTree = ref;
36d6a7ad0dSToby Isaac   PetscFunctionReturn(0);
37d6a7ad0dSToby Isaac }
38d6a7ad0dSToby Isaac 
39d6a7ad0dSToby Isaac #undef __FUNCT__
40d6a7ad0dSToby Isaac #define __FUNCT__ "DMPlexGetReferenceTree"
41d6a7ad0dSToby Isaac /*@
42d6a7ad0dSToby Isaac   DMPlexGetReferenceTree - get the reference tree for hierarchically non-conforming meshes.
43d6a7ad0dSToby Isaac 
44d6a7ad0dSToby Isaac   Not collective
45d6a7ad0dSToby Isaac 
46d6a7ad0dSToby Isaac   Input Parameters:
47d6a7ad0dSToby Isaac . dm - The DMPlex object
48d6a7ad0dSToby Isaac 
49d6a7ad0dSToby Isaac   Output Parameters
50d6a7ad0dSToby Isaac . ref - The reference tree DMPlex object
51d6a7ad0dSToby Isaac 
520b7167a0SToby Isaac   Level: intermediate
53d6a7ad0dSToby Isaac 
54da43764aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexCreateDefaultReferenceTree()
55d6a7ad0dSToby Isaac @*/
56d6a7ad0dSToby Isaac PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref)
57d6a7ad0dSToby Isaac {
58d6a7ad0dSToby Isaac   DM_Plex        *mesh = (DM_Plex *)dm->data;
59d6a7ad0dSToby Isaac 
60d6a7ad0dSToby Isaac   PetscFunctionBegin;
61d6a7ad0dSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62d6a7ad0dSToby Isaac   PetscValidPointer(ref,2);
63d6a7ad0dSToby Isaac   *ref = mesh->referenceTree;
64d6a7ad0dSToby Isaac   PetscFunctionReturn(0);
65d6a7ad0dSToby Isaac }
66d6a7ad0dSToby Isaac 
67dcbd3bf7SToby Isaac #undef __FUNCT__
68dcbd3bf7SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildSymmetry_Default"
69dcbd3bf7SToby Isaac static PetscErrorCode DMPlexReferenceTreeGetChildSymmetry_Default(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB)
70dcbd3bf7SToby Isaac {
71dcbd3bf7SToby Isaac   PetscInt       coneSize, dStart, dEnd, dim, ABswap, oAvert, oBvert, ABswapVert;
72dcbd3bf7SToby Isaac   PetscErrorCode ierr;
73dcbd3bf7SToby Isaac 
74dcbd3bf7SToby Isaac   PetscFunctionBegin;
75dcbd3bf7SToby Isaac   if (parentOrientA == parentOrientB) {
76dcbd3bf7SToby Isaac     if (childOrientB) *childOrientB = childOrientA;
77dcbd3bf7SToby Isaac     if (childB) *childB = childA;
78dcbd3bf7SToby Isaac     PetscFunctionReturn(0);
79dcbd3bf7SToby Isaac   }
80dcbd3bf7SToby Isaac   for (dim = 0; dim < 3; dim++) {
81dcbd3bf7SToby Isaac     ierr = DMPlexGetDepthStratum(dm,dim,&dStart,&dEnd);CHKERRQ(ierr);
82dcbd3bf7SToby Isaac     if (parent >= dStart && parent <= dEnd) {
83dcbd3bf7SToby Isaac       break;
84dcbd3bf7SToby Isaac     }
85dcbd3bf7SToby Isaac   }
86dcbd3bf7SToby Isaac   if (dim > 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot perform child symmetry for %d-cells",dim);
87dcbd3bf7SToby Isaac   if (!dim) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"A vertex has no children");
88dcbd3bf7SToby Isaac   if (childA < dStart || childA >= dEnd) {
89dcbd3bf7SToby Isaac     /* this is a lower-dimensional child: bootstrap */
90dcbd3bf7SToby Isaac     PetscInt size, i, sA = -1, sB, sOrientB, sConeSize;
91dcbd3bf7SToby Isaac     const PetscInt *supp, *coneA, *coneB, *oA, *oB;
92dcbd3bf7SToby Isaac 
93dcbd3bf7SToby Isaac     ierr = DMPlexGetSupportSize(dm,childA,&size);CHKERRQ(ierr);
94dcbd3bf7SToby Isaac     ierr = DMPlexGetSupport(dm,childA,&supp);CHKERRQ(ierr);
95dcbd3bf7SToby Isaac 
96dcbd3bf7SToby Isaac     /* find a point sA in supp(childA) that has the same parent */
97dcbd3bf7SToby Isaac     for (i = 0; i < size; i++) {
98dcbd3bf7SToby Isaac       PetscInt sParent;
99dcbd3bf7SToby Isaac 
100dcbd3bf7SToby Isaac       sA   = supp[i];
101dcbd3bf7SToby Isaac       if (sA == parent) continue;
102dcbd3bf7SToby Isaac       ierr = DMPlexGetTreeParent(dm,sA,&sParent,NULL);CHKERRQ(ierr);
103dcbd3bf7SToby Isaac       if (sParent == parent) {
104dcbd3bf7SToby Isaac         break;
105dcbd3bf7SToby Isaac       }
106dcbd3bf7SToby Isaac     }
107dcbd3bf7SToby Isaac     if (i == size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"could not find support in children");
108dcbd3bf7SToby Isaac     /* find out which point sB is in an equivalent position to sA under
109dcbd3bf7SToby Isaac      * parentOrientB */
110dcbd3bf7SToby Isaac     ierr = DMPlexReferenceTreeGetChildSymmetry_Default(dm,parent,parentOrientA,0,sA,parentOrientB,&sOrientB,&sB);CHKERRQ(ierr);
111dcbd3bf7SToby Isaac     ierr = DMPlexGetConeSize(dm,sA,&sConeSize);CHKERRQ(ierr);
112dcbd3bf7SToby Isaac     ierr = DMPlexGetCone(dm,sA,&coneA);CHKERRQ(ierr);
113dcbd3bf7SToby Isaac     ierr = DMPlexGetCone(dm,sB,&coneB);CHKERRQ(ierr);
114dcbd3bf7SToby Isaac     ierr = DMPlexGetConeOrientation(dm,sA,&oA);CHKERRQ(ierr);
115dcbd3bf7SToby Isaac     ierr = DMPlexGetConeOrientation(dm,sB,&oB);CHKERRQ(ierr);
116dcbd3bf7SToby Isaac     /* step through the cone of sA in natural order */
117dcbd3bf7SToby Isaac     for (i = 0; i < sConeSize; i++) {
118dcbd3bf7SToby Isaac       if (coneA[i] == childA) {
119dcbd3bf7SToby Isaac         /* if childA is at position i in coneA,
120dcbd3bf7SToby Isaac          * then we want the point that is at sOrientB*i in coneB */
121dcbd3bf7SToby Isaac         PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize -(sOrientB+1) - i) % sConeSize);
122dcbd3bf7SToby Isaac         if (childB) *childB = coneB[j];
123dcbd3bf7SToby Isaac         if (childOrientB) {
124dcbd3bf7SToby Isaac           PetscInt oBtrue;
125dcbd3bf7SToby Isaac 
126dcbd3bf7SToby Isaac           ierr          = DMPlexGetConeSize(dm,childA,&coneSize);CHKERRQ(ierr);
127dcbd3bf7SToby Isaac           /* compose sOrientB and oB[j] */
128dcbd3bf7SToby Isaac           if (coneSize != 0 && coneSize != 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected a vertex or an edge");
129dcbd3bf7SToby Isaac           /* we may have to flip an edge */
130dcbd3bf7SToby Isaac           oBtrue        = coneSize ? ((sOrientB >= 0) ? oB[j] : -(oB[j] + 2)) : 0;
131dcbd3bf7SToby Isaac           ABswap        = DihedralSwap(coneSize,oA[i],oBtrue);CHKERRQ(ierr);
132dcbd3bf7SToby Isaac           *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap);
133dcbd3bf7SToby Isaac         }
134dcbd3bf7SToby Isaac         break;
135dcbd3bf7SToby Isaac       }
136dcbd3bf7SToby Isaac     }
137dcbd3bf7SToby Isaac     if (i == sConeSize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"support cone mismatch");
138dcbd3bf7SToby Isaac     PetscFunctionReturn(0);
139dcbd3bf7SToby Isaac   }
140dcbd3bf7SToby Isaac   /* get the cone size and symmetry swap */
141dcbd3bf7SToby Isaac   ierr   = DMPlexGetConeSize(dm,parent,&coneSize);CHKERRQ(ierr);
142dcbd3bf7SToby Isaac   ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB);
143dcbd3bf7SToby Isaac   if (dim == 2) {
144dcbd3bf7SToby Isaac     /* orientations refer to cones: we want them to refer to vertices:
145dcbd3bf7SToby Isaac      * if it's a rotation, they are the same, but if the order is reversed, a
146dcbd3bf7SToby Isaac      * permutation that puts side i first does *not* put vertex i first */
147dcbd3bf7SToby Isaac     oAvert     = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1);
148dcbd3bf7SToby Isaac     oBvert     = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1);
149dcbd3bf7SToby Isaac     ABswapVert = DihedralSwap(coneSize, oAvert, oBvert);
150dcbd3bf7SToby Isaac   }
151dcbd3bf7SToby Isaac   else {
152dcbd3bf7SToby Isaac     oAvert     = parentOrientA;
153dcbd3bf7SToby Isaac     oBvert     = parentOrientB;
154dcbd3bf7SToby Isaac     ABswapVert = ABswap;
155dcbd3bf7SToby Isaac   }
156dcbd3bf7SToby Isaac   if (childB) {
157dcbd3bf7SToby Isaac     /* assume that each child corresponds to a vertex, in the same order */
158dcbd3bf7SToby Isaac     PetscInt p, posA = -1, numChildren, i;
159dcbd3bf7SToby Isaac     const PetscInt *children;
160dcbd3bf7SToby Isaac 
161dcbd3bf7SToby Isaac     /* count which position the child is in */
162dcbd3bf7SToby Isaac     ierr = DMPlexGetTreeChildren(dm,parent,&numChildren,&children);CHKERRQ(ierr);
163dcbd3bf7SToby Isaac     for (i = 0; i < numChildren; i++) {
164dcbd3bf7SToby Isaac       p = children[i];
165dcbd3bf7SToby Isaac       if (p == childA) {
166dcbd3bf7SToby Isaac         posA = i;
167dcbd3bf7SToby Isaac         break;
168dcbd3bf7SToby Isaac       }
169dcbd3bf7SToby Isaac     }
170dcbd3bf7SToby Isaac     if (posA >= coneSize) {
171dcbd3bf7SToby Isaac       /* this is the triangle in the middle of a uniformly refined triangle: it
172dcbd3bf7SToby Isaac        * is invariant */
173dcbd3bf7SToby Isaac       if (dim != 2 || posA != 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Expected a middle triangle, got something else");
174dcbd3bf7SToby Isaac       *childB = childA;
175dcbd3bf7SToby Isaac     }
176dcbd3bf7SToby Isaac     else {
177dcbd3bf7SToby Isaac       /* figure out position B by applying ABswapVert */
178dcbd3bf7SToby Isaac       PetscInt posB;
179dcbd3bf7SToby Isaac 
180dcbd3bf7SToby Isaac       posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize -(ABswapVert + 1) - posA) % coneSize);
181dcbd3bf7SToby Isaac       if (childB) *childB = children[posB];
182dcbd3bf7SToby Isaac     }
183dcbd3bf7SToby Isaac   }
184dcbd3bf7SToby Isaac   if (childOrientB) *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap);
185dcbd3bf7SToby Isaac   PetscFunctionReturn(0);
186dcbd3bf7SToby Isaac }
187dcbd3bf7SToby Isaac 
188dcbd3bf7SToby Isaac #undef __FUNCT__
189dcbd3bf7SToby Isaac #define __FUNCT__ "DMPlexReferenceTreeGetChildSymmetry"
190dcbd3bf7SToby Isaac /*@
191dcbd3bf7SToby Isaac   DMPlexReferenceTreeGetChildSymmetry - Given a reference tree, transform a childid and orientation from one parent frame to another
192dcbd3bf7SToby Isaac 
193dcbd3bf7SToby Isaac   Input Parameters:
194dcbd3bf7SToby Isaac + dm - the reference tree DMPlex object
195dcbd3bf7SToby Isaac . parent - the parent point
196dcbd3bf7SToby Isaac . parentOrientA - the reference orientation for describing the parent
197dcbd3bf7SToby Isaac . childOrientA - the reference orientation for describing the child
198dcbd3bf7SToby Isaac . childA - the reference childID for describing the child
199dcbd3bf7SToby Isaac - parentOrientB - the new orientation for describing the parent
200dcbd3bf7SToby Isaac 
201dcbd3bf7SToby Isaac   Output Parameters:
202dcbd3bf7SToby Isaac + childOrientB - if not NULL, set to the new oreintation for describing the child
203dcbd3bf7SToby Isaac . childB - if not NULL, the new childID for describing the child
204dcbd3bf7SToby Isaac 
205dcbd3bf7SToby Isaac   Level: developer
206dcbd3bf7SToby Isaac 
207dcbd3bf7SToby Isaac .seealso: DMPlexGetReferenceTree(), DMPlexSetReferenceTree(), DMPlexSetTree()
208dcbd3bf7SToby Isaac @*/
209dcbd3bf7SToby Isaac PetscErrorCode DMPlexReferenceTreeGetChildSymmetry(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB)
210dcbd3bf7SToby Isaac {
211dcbd3bf7SToby Isaac   DM_Plex        *mesh = (DM_Plex *)dm->data;
212dcbd3bf7SToby Isaac   PetscErrorCode ierr;
213dcbd3bf7SToby Isaac 
214dcbd3bf7SToby Isaac   PetscFunctionBegin;
215dcbd3bf7SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
216dcbd3bf7SToby Isaac   if (!mesh->getchildsymmetry) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"DMPlexReferenceTreeGetChildSymmetry not implemented");
217dcbd3bf7SToby Isaac   ierr = mesh->getchildsymmetry(dm,parent,parentOrientA,childOrientA,childA,parentOrientB,childOrientB,childB);CHKERRQ(ierr);
218dcbd3bf7SToby Isaac   PetscFunctionReturn(0);
219dcbd3bf7SToby Isaac }
220dcbd3bf7SToby Isaac 
221776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM,PetscSection,PetscInt*,PetscInt*,PetscBool,PetscBool);
222f9f063d4SToby Isaac 
223da43764aSToby Isaac #undef __FUNCT__
2240e2cc29aSToby Isaac #define __FUNCT__ "DMPlexCreateReferenceTree_Union"
2250e2cc29aSToby Isaac PetscErrorCode DMPlexCreateReferenceTree_Union(DM K, DM Kref, const char *labelName, DM *ref)
226da43764aSToby Isaac {
2270e2cc29aSToby Isaac   MPI_Comm       comm;
2280e2cc29aSToby Isaac   PetscInt       dim, p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs;
229da43764aSToby Isaac   PetscInt      *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts;
230da43764aSToby Isaac   DMLabel        identity, identityRef;
23110f7e118SToby Isaac   PetscSection   unionSection, unionConeSection, parentSection;
232da43764aSToby Isaac   PetscScalar   *unionCoords;
233da43764aSToby Isaac   IS             perm;
234da43764aSToby Isaac   PetscErrorCode ierr;
235da43764aSToby Isaac 
236da43764aSToby Isaac   PetscFunctionBegin;
2370e2cc29aSToby Isaac   comm = PetscObjectComm((PetscObject)K);
2380e2cc29aSToby Isaac   ierr = DMGetDimension(K, &dim);CHKERRQ(ierr);
239da43764aSToby Isaac   ierr = DMPlexGetChart(K, &pStart, &pEnd);CHKERRQ(ierr);
2400e2cc29aSToby Isaac   ierr = DMGetLabel(K, labelName, &identity);CHKERRQ(ierr);
2410e2cc29aSToby Isaac   ierr = DMGetLabel(Kref, labelName, &identityRef);CHKERRQ(ierr);
242da43764aSToby Isaac   ierr = DMPlexGetChart(Kref, &pRefStart, &pRefEnd);CHKERRQ(ierr);
243da43764aSToby Isaac   ierr = PetscSectionCreate(comm, &unionSection);CHKERRQ(ierr);
244da43764aSToby Isaac   ierr = PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart));CHKERRQ(ierr);
245da43764aSToby Isaac   /* count points that will go in the union */
246da43764aSToby Isaac   for (p = pStart; p < pEnd; p++) {
247da43764aSToby Isaac     ierr = PetscSectionSetDof(unionSection, p - pStart, 1);CHKERRQ(ierr);
248da43764aSToby Isaac   }
249da43764aSToby Isaac   for (p = pRefStart; p < pRefEnd; p++) {
250da43764aSToby Isaac     PetscInt q, qSize;
251da43764aSToby Isaac     ierr = DMLabelGetValue(identityRef, p, &q);CHKERRQ(ierr);
252da43764aSToby Isaac     ierr = DMLabelGetStratumSize(identityRef, q, &qSize);CHKERRQ(ierr);
253da43764aSToby Isaac     if (qSize > 1) {
254da43764aSToby Isaac       ierr = PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1);CHKERRQ(ierr);
255da43764aSToby Isaac     }
256da43764aSToby Isaac   }
257854ce69bSBarry Smith   ierr = PetscMalloc1(pEnd - pStart + pRefEnd - pRefStart,&permvals);CHKERRQ(ierr);
258da43764aSToby Isaac   offset = 0;
259da43764aSToby Isaac   /* stratify points in the union by topological dimension */
260da43764aSToby Isaac   for (d = 0; d <= dim; d++) {
261da43764aSToby Isaac     PetscInt cStart, cEnd, c;
262da43764aSToby Isaac 
263da43764aSToby Isaac     ierr = DMPlexGetHeightStratum(K, d, &cStart, &cEnd);CHKERRQ(ierr);
264da43764aSToby Isaac     for (c = cStart; c < cEnd; c++) {
265da43764aSToby Isaac       permvals[offset++] = c;
266da43764aSToby Isaac     }
267da43764aSToby Isaac 
268da43764aSToby Isaac     ierr = DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd);CHKERRQ(ierr);
269da43764aSToby Isaac     for (c = cStart; c < cEnd; c++) {
270da43764aSToby Isaac       permvals[offset++] = c + (pEnd - pStart);
271da43764aSToby Isaac     }
272da43764aSToby Isaac   }
273da43764aSToby Isaac   ierr = ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm);CHKERRQ(ierr);
274da43764aSToby Isaac   ierr = PetscSectionSetPermutation(unionSection,perm);CHKERRQ(ierr);
275da43764aSToby Isaac   ierr = PetscSectionSetUp(unionSection);CHKERRQ(ierr);
276da43764aSToby Isaac   ierr = PetscSectionGetStorageSize(unionSection,&numUnionPoints);CHKERRQ(ierr);
277da43764aSToby Isaac   ierr = PetscMalloc2(numUnionPoints,&coneSizes,dim+1,&numDimPoints);CHKERRQ(ierr);
278da43764aSToby Isaac   /* count dimension points */
279da43764aSToby Isaac   for (d = 0; d <= dim; d++) {
280da43764aSToby Isaac     PetscInt cStart, cOff, cOff2;
281da43764aSToby Isaac     ierr = DMPlexGetHeightStratum(K,d,&cStart,NULL);CHKERRQ(ierr);
282da43764aSToby Isaac     ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff);CHKERRQ(ierr);
283da43764aSToby Isaac     if (d < dim) {
284da43764aSToby Isaac       ierr = DMPlexGetHeightStratum(K,d+1,&cStart,NULL);CHKERRQ(ierr);
285da43764aSToby Isaac       ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff2);CHKERRQ(ierr);
286da43764aSToby Isaac     }
287da43764aSToby Isaac     else {
288da43764aSToby Isaac       cOff2 = numUnionPoints;
289da43764aSToby Isaac     }
290da43764aSToby Isaac     numDimPoints[dim - d] = cOff2 - cOff;
291da43764aSToby Isaac   }
292da43764aSToby Isaac   ierr = PetscSectionCreate(comm, &unionConeSection);CHKERRQ(ierr);
293da43764aSToby Isaac   ierr = PetscSectionSetChart(unionConeSection, 0, numUnionPoints);CHKERRQ(ierr);
294da43764aSToby Isaac   /* count the cones in the union */
295da43764aSToby Isaac   for (p = pStart; p < pEnd; p++) {
296da43764aSToby Isaac     PetscInt dof, uOff;
297da43764aSToby Isaac 
298da43764aSToby Isaac     ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr);
299da43764aSToby Isaac     ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr);
300da43764aSToby Isaac     ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr);
301da43764aSToby Isaac     coneSizes[uOff] = dof;
302da43764aSToby Isaac   }
303da43764aSToby Isaac   for (p = pRefStart; p < pRefEnd; p++) {
304da43764aSToby Isaac     PetscInt dof, uDof, uOff;
305da43764aSToby Isaac 
306da43764aSToby Isaac     ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr);
307da43764aSToby Isaac     ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr);
308da43764aSToby Isaac     ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr);
309da43764aSToby Isaac     if (uDof) {
310da43764aSToby Isaac       ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr);
311da43764aSToby Isaac       coneSizes[uOff] = dof;
312da43764aSToby Isaac     }
313da43764aSToby Isaac   }
314da43764aSToby Isaac   ierr = PetscSectionSetUp(unionConeSection);CHKERRQ(ierr);
315da43764aSToby Isaac   ierr = PetscSectionGetStorageSize(unionConeSection,&numCones);CHKERRQ(ierr);
316da43764aSToby Isaac   ierr = PetscMalloc2(numCones,&unionCones,numCones,&unionOrientations);CHKERRQ(ierr);
317da43764aSToby Isaac   /* write the cones in the union */
318da43764aSToby Isaac   for (p = pStart; p < pEnd; p++) {
319da43764aSToby Isaac     PetscInt dof, uOff, c, cOff;
320da43764aSToby Isaac     const PetscInt *cone, *orientation;
321da43764aSToby Isaac 
322da43764aSToby Isaac     ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr);
323da43764aSToby Isaac     ierr = DMPlexGetCone(K, p, &cone);CHKERRQ(ierr);
324da43764aSToby Isaac     ierr = DMPlexGetConeOrientation(K, p, &orientation);CHKERRQ(ierr);
325da43764aSToby Isaac     ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr);
326da43764aSToby Isaac     ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr);
327da43764aSToby Isaac     for (c = 0; c < dof; c++) {
328da43764aSToby Isaac       PetscInt e, eOff;
329da43764aSToby Isaac       e                           = cone[c];
330da43764aSToby Isaac       ierr                        = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr);
331da43764aSToby Isaac       unionCones[cOff + c]        = eOff;
332da43764aSToby Isaac       unionOrientations[cOff + c] = orientation[c];
333da43764aSToby Isaac     }
334da43764aSToby Isaac   }
335da43764aSToby Isaac   for (p = pRefStart; p < pRefEnd; p++) {
336da43764aSToby Isaac     PetscInt dof, uDof, uOff, c, cOff;
337da43764aSToby Isaac     const PetscInt *cone, *orientation;
338da43764aSToby Isaac 
339da43764aSToby Isaac     ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr);
340da43764aSToby Isaac     ierr = DMPlexGetCone(Kref, p, &cone);CHKERRQ(ierr);
341da43764aSToby Isaac     ierr = DMPlexGetConeOrientation(Kref, p, &orientation);CHKERRQ(ierr);
342da43764aSToby Isaac     ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr);
343da43764aSToby Isaac     ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr);
344da43764aSToby Isaac     if (uDof) {
345da43764aSToby Isaac       ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr);
346da43764aSToby Isaac       for (c = 0; c < dof; c++) {
347da43764aSToby Isaac         PetscInt e, eOff, eDof;
348da43764aSToby Isaac 
349da43764aSToby Isaac         e    = cone[c];
350da43764aSToby Isaac         ierr = PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart),&eDof);CHKERRQ(ierr);
351da43764aSToby Isaac         if (eDof) {
352da43764aSToby Isaac           ierr = PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff);CHKERRQ(ierr);
353da43764aSToby Isaac         }
354da43764aSToby Isaac         else {
355da43764aSToby Isaac           ierr = DMLabelGetValue(identityRef, e, &e);CHKERRQ(ierr);
356da43764aSToby Isaac           ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr);
357da43764aSToby Isaac         }
358da43764aSToby Isaac         unionCones[cOff + c]        = eOff;
359da43764aSToby Isaac         unionOrientations[cOff + c] = orientation[c];
360da43764aSToby Isaac       }
361da43764aSToby Isaac     }
362da43764aSToby Isaac   }
363da43764aSToby Isaac   /* get the coordinates */
364da43764aSToby Isaac   {
365da43764aSToby Isaac     PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff;
366da43764aSToby Isaac     PetscSection KcoordsSec, KrefCoordsSec;
367da43764aSToby Isaac     Vec      KcoordsVec, KrefCoordsVec;
368da43764aSToby Isaac     PetscScalar *Kcoords;
369da43764aSToby Isaac 
370da43764aSToby Isaac     DMGetCoordinateSection(K, &KcoordsSec);CHKERRQ(ierr);
371da43764aSToby Isaac     DMGetCoordinatesLocal(K, &KcoordsVec);CHKERRQ(ierr);
372da43764aSToby Isaac     DMGetCoordinateSection(Kref, &KrefCoordsSec);CHKERRQ(ierr);
373da43764aSToby Isaac     DMGetCoordinatesLocal(Kref, &KrefCoordsVec);CHKERRQ(ierr);
374da43764aSToby Isaac 
375da43764aSToby Isaac     numVerts = numDimPoints[0];
376da43764aSToby Isaac     ierr     = PetscMalloc1(numVerts * dim,&unionCoords);CHKERRQ(ierr);
377da43764aSToby Isaac     ierr     = DMPlexGetDepthStratum(K,0,&vStart,&vEnd);CHKERRQ(ierr);
378da43764aSToby Isaac 
379da43764aSToby Isaac     offset = 0;
380da43764aSToby Isaac     for (v = vStart; v < vEnd; v++) {
381da43764aSToby Isaac       ierr = PetscSectionGetOffset(unionSection,v - pStart,&vOff);CHKERRQ(ierr);
382da43764aSToby Isaac       ierr = VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords);CHKERRQ(ierr);
383da43764aSToby Isaac       for (d = 0; d < dim; d++) {
384da43764aSToby Isaac         unionCoords[offset * dim + d] = Kcoords[d];
385da43764aSToby Isaac       }
386da43764aSToby Isaac       offset++;
387da43764aSToby Isaac     }
388da43764aSToby Isaac     ierr = DMPlexGetDepthStratum(Kref,0,&vRefStart,&vRefEnd);CHKERRQ(ierr);
389da43764aSToby Isaac     for (v = vRefStart; v < vRefEnd; v++) {
390da43764aSToby Isaac       ierr = PetscSectionGetDof(unionSection,v - pRefStart + (pEnd - pStart),&vDof);CHKERRQ(ierr);
391da43764aSToby Isaac       ierr = PetscSectionGetOffset(unionSection,v - pRefStart + (pEnd - pStart),&vOff);CHKERRQ(ierr);
392da43764aSToby Isaac       ierr = VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords);CHKERRQ(ierr);
393da43764aSToby Isaac       if (vDof) {
394da43764aSToby Isaac         for (d = 0; d < dim; d++) {
395da43764aSToby Isaac           unionCoords[offset * dim + d] = Kcoords[d];
396da43764aSToby Isaac         }
397da43764aSToby Isaac         offset++;
398da43764aSToby Isaac       }
399da43764aSToby Isaac     }
400da43764aSToby Isaac   }
401da43764aSToby Isaac   ierr = DMCreate(comm,ref);CHKERRQ(ierr);
402da43764aSToby Isaac   ierr = DMSetType(*ref,DMPLEX);CHKERRQ(ierr);
40328f4b327SMatthew G. Knepley   ierr = DMSetDimension(*ref,dim);CHKERRQ(ierr);
404da43764aSToby Isaac   ierr = DMPlexCreateFromDAG(*ref,dim,numDimPoints,coneSizes,unionCones,unionOrientations,unionCoords);CHKERRQ(ierr);
40510f7e118SToby Isaac   /* set the tree */
40610f7e118SToby Isaac   ierr = PetscSectionCreate(comm,&parentSection);CHKERRQ(ierr);
40710f7e118SToby Isaac   ierr = PetscSectionSetChart(parentSection,0,numUnionPoints);CHKERRQ(ierr);
40810f7e118SToby Isaac   for (p = pRefStart; p < pRefEnd; p++) {
40910f7e118SToby Isaac     PetscInt uDof, uOff;
41010f7e118SToby Isaac 
41110f7e118SToby Isaac     ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr);
41210f7e118SToby Isaac     ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr);
41310f7e118SToby Isaac     if (uDof) {
41410f7e118SToby Isaac       PetscSectionSetDof(parentSection,uOff,1);CHKERRQ(ierr);
41510f7e118SToby Isaac     }
41610f7e118SToby Isaac   }
41710f7e118SToby Isaac   ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr);
41810f7e118SToby Isaac   ierr = PetscSectionGetStorageSize(parentSection,&parentSize);CHKERRQ(ierr);
41910f7e118SToby Isaac   ierr = PetscMalloc2(parentSize,&parents,parentSize,&childIDs);CHKERRQ(ierr);
42010f7e118SToby Isaac   for (p = pRefStart; p < pRefEnd; p++) {
42110f7e118SToby Isaac     PetscInt uDof, uOff;
42210f7e118SToby Isaac 
42310f7e118SToby Isaac     ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr);
42410f7e118SToby Isaac     ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr);
42510f7e118SToby Isaac     if (uDof) {
42610f7e118SToby Isaac       PetscInt pOff, parent, parentU;
42710f7e118SToby Isaac       PetscSectionGetOffset(parentSection,uOff,&pOff);CHKERRQ(ierr);
42810f7e118SToby Isaac       DMLabelGetValue(identityRef,p,&parent);CHKERRQ(ierr);
42910f7e118SToby Isaac       ierr = PetscSectionGetOffset(unionSection, parent - pStart,&parentU);CHKERRQ(ierr);
43010f7e118SToby Isaac       parents[pOff] = parentU;
43110f7e118SToby Isaac       childIDs[pOff] = uOff;
43210f7e118SToby Isaac     }
43310f7e118SToby Isaac   }
434776742edSToby Isaac   ierr = DMPlexSetTree_Internal(*ref,parentSection,parents,childIDs,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
43510f7e118SToby Isaac   ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr);
43610f7e118SToby Isaac   ierr = PetscFree2(parents,childIDs);CHKERRQ(ierr);
43710f7e118SToby Isaac 
438da43764aSToby Isaac   /* clean up */
439da43764aSToby Isaac   ierr = PetscSectionDestroy(&unionSection);CHKERRQ(ierr);
440da43764aSToby Isaac   ierr = PetscSectionDestroy(&unionConeSection);CHKERRQ(ierr);
441da43764aSToby Isaac   ierr = ISDestroy(&perm);CHKERRQ(ierr);
442da43764aSToby Isaac   ierr = PetscFree(unionCoords);CHKERRQ(ierr);
443da43764aSToby Isaac   ierr = PetscFree2(unionCones,unionOrientations);CHKERRQ(ierr);
444da43764aSToby Isaac   ierr = PetscFree2(coneSizes,numDimPoints);CHKERRQ(ierr);
4450e2cc29aSToby Isaac   PetscFunctionReturn(0);
4460e2cc29aSToby Isaac }
4470e2cc29aSToby Isaac 
4480e2cc29aSToby Isaac #undef __FUNCT__
4490e2cc29aSToby Isaac #define __FUNCT__ "DMPlexCreateDefaultReferenceTree"
4500e2cc29aSToby Isaac /*@
4510e2cc29aSToby Isaac   DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement.
4520e2cc29aSToby Isaac 
4530e2cc29aSToby Isaac   Collective on comm
4540e2cc29aSToby Isaac 
4550e2cc29aSToby Isaac   Input Parameters:
4560e2cc29aSToby Isaac + comm    - the MPI communicator
4570e2cc29aSToby Isaac . dim     - the spatial dimension
4580e2cc29aSToby Isaac - simplex - Flag for simplex, otherwise use a tensor-product cell
4590e2cc29aSToby Isaac 
4600e2cc29aSToby Isaac   Output Parameters:
4610e2cc29aSToby Isaac . ref     - the reference tree DMPlex object
4620e2cc29aSToby Isaac 
4630e2cc29aSToby Isaac   Level: intermediate
4640e2cc29aSToby Isaac 
4650e2cc29aSToby Isaac .keywords: reference cell
4660e2cc29aSToby Isaac .seealso: DMPlexSetReferenceTree(), DMPlexGetReferenceTree()
4670e2cc29aSToby Isaac @*/
4680e2cc29aSToby Isaac PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref)
4690e2cc29aSToby Isaac {
4700e2cc29aSToby Isaac   DM_Plex       *mesh;
4710e2cc29aSToby Isaac   DM             K, Kref;
4720e2cc29aSToby Isaac   PetscInt       p, pStart, pEnd;
4730e2cc29aSToby Isaac   DMLabel        identity;
4740e2cc29aSToby Isaac   PetscErrorCode ierr;
4750e2cc29aSToby Isaac 
4760e2cc29aSToby Isaac   PetscFunctionBegin;
4770e2cc29aSToby Isaac #if 1
4780e2cc29aSToby Isaac   comm = PETSC_COMM_SELF;
4790e2cc29aSToby Isaac #endif
4800e2cc29aSToby Isaac   /* create a reference element */
4810e2cc29aSToby Isaac   ierr = DMPlexCreateReferenceCell(comm, dim, simplex, &K);CHKERRQ(ierr);
4820e2cc29aSToby Isaac   ierr = DMCreateLabel(K, "identity");CHKERRQ(ierr);
4830e2cc29aSToby Isaac   ierr = DMGetLabel(K, "identity", &identity);CHKERRQ(ierr);
4840e2cc29aSToby Isaac   ierr = DMPlexGetChart(K, &pStart, &pEnd);CHKERRQ(ierr);
4850e2cc29aSToby Isaac   for (p = pStart; p < pEnd; p++) {
4860e2cc29aSToby Isaac     ierr = DMLabelSetValue(identity, p, p);CHKERRQ(ierr);
4870e2cc29aSToby Isaac   }
4880e2cc29aSToby Isaac   /* refine it */
4890e2cc29aSToby Isaac   ierr = DMRefine(K,comm,&Kref);CHKERRQ(ierr);
4900e2cc29aSToby Isaac 
4910e2cc29aSToby Isaac   /* the reference tree is the union of these two, without duplicating
4920e2cc29aSToby Isaac    * points that appear in both */
4930e2cc29aSToby Isaac   ierr = DMPlexCreateReferenceTree_Union(K, Kref, "identity", ref);CHKERRQ(ierr);
4940e2cc29aSToby Isaac   mesh = (DM_Plex *) (*ref)->data;
4950e2cc29aSToby Isaac   mesh->getchildsymmetry = DMPlexReferenceTreeGetChildSymmetry_Default;
496da43764aSToby Isaac   ierr = DMDestroy(&K);CHKERRQ(ierr);
497da43764aSToby Isaac   ierr = DMDestroy(&Kref);CHKERRQ(ierr);
498da43764aSToby Isaac   PetscFunctionReturn(0);
499da43764aSToby Isaac }
500da43764aSToby Isaac 
501d961a43aSToby Isaac #undef __FUNCT__
502878b19aaSToby Isaac #define __FUNCT__ "DMPlexTreeSymmetrize"
503878b19aaSToby Isaac static PetscErrorCode DMPlexTreeSymmetrize(DM dm)
504878b19aaSToby Isaac {
505878b19aaSToby Isaac   DM_Plex        *mesh = (DM_Plex *)dm->data;
506878b19aaSToby Isaac   PetscSection   childSec, pSec;
507878b19aaSToby Isaac   PetscInt       p, pSize, cSize, parMax = PETSC_MIN_INT, parMin = PETSC_MAX_INT;
508878b19aaSToby Isaac   PetscInt       *offsets, *children, pStart, pEnd;
509878b19aaSToby Isaac   PetscErrorCode ierr;
510878b19aaSToby Isaac 
511878b19aaSToby Isaac   PetscFunctionBegin;
512878b19aaSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
513878b19aaSToby Isaac   ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr);
514878b19aaSToby Isaac   ierr = PetscFree(mesh->children);CHKERRQ(ierr);
515878b19aaSToby Isaac   pSec = mesh->parentSection;
516878b19aaSToby Isaac   if (!pSec) PetscFunctionReturn(0);
517878b19aaSToby Isaac   ierr = PetscSectionGetStorageSize(pSec,&pSize);CHKERRQ(ierr);
518878b19aaSToby Isaac   for (p = 0; p < pSize; p++) {
519878b19aaSToby Isaac     PetscInt par = mesh->parents[p];
520878b19aaSToby Isaac 
521878b19aaSToby Isaac     parMax = PetscMax(parMax,par+1);
522878b19aaSToby Isaac     parMin = PetscMin(parMin,par);
523878b19aaSToby Isaac   }
524878b19aaSToby Isaac   if (parMin > parMax) {
525878b19aaSToby Isaac     parMin = -1;
526878b19aaSToby Isaac     parMax = -1;
527878b19aaSToby Isaac   }
528878b19aaSToby Isaac   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)pSec),&childSec);CHKERRQ(ierr);
529878b19aaSToby Isaac   ierr = PetscSectionSetChart(childSec,parMin,parMax);CHKERRQ(ierr);
530878b19aaSToby Isaac   for (p = 0; p < pSize; p++) {
531878b19aaSToby Isaac     PetscInt par = mesh->parents[p];
532878b19aaSToby Isaac 
533878b19aaSToby Isaac     ierr = PetscSectionAddDof(childSec,par,1);CHKERRQ(ierr);
534878b19aaSToby Isaac   }
535878b19aaSToby Isaac   ierr = PetscSectionSetUp(childSec);CHKERRQ(ierr);
536878b19aaSToby Isaac   ierr = PetscSectionGetStorageSize(childSec,&cSize);CHKERRQ(ierr);
537878b19aaSToby Isaac   ierr = PetscMalloc1(cSize,&children);CHKERRQ(ierr);
538878b19aaSToby Isaac   ierr = PetscCalloc1(parMax-parMin,&offsets);CHKERRQ(ierr);
539878b19aaSToby Isaac   ierr = PetscSectionGetChart(pSec,&pStart,&pEnd);CHKERRQ(ierr);
540878b19aaSToby Isaac   for (p = pStart; p < pEnd; p++) {
541878b19aaSToby Isaac     PetscInt dof, off, i;
542878b19aaSToby Isaac 
543878b19aaSToby Isaac     ierr = PetscSectionGetDof(pSec,p,&dof);CHKERRQ(ierr);
544878b19aaSToby Isaac     ierr = PetscSectionGetOffset(pSec,p,&off);CHKERRQ(ierr);
545878b19aaSToby Isaac     for (i = 0; i < dof; i++) {
546878b19aaSToby Isaac       PetscInt par = mesh->parents[off + i], cOff;
547878b19aaSToby Isaac 
548878b19aaSToby Isaac       ierr = PetscSectionGetOffset(childSec,par,&cOff);CHKERRQ(ierr);
549878b19aaSToby Isaac       children[cOff + offsets[par-parMin]++] = p;
550878b19aaSToby Isaac     }
551878b19aaSToby Isaac   }
552878b19aaSToby Isaac   mesh->childSection = childSec;
553878b19aaSToby Isaac   mesh->children = children;
554878b19aaSToby Isaac   ierr = PetscFree(offsets);CHKERRQ(ierr);
555878b19aaSToby Isaac   PetscFunctionReturn(0);
556878b19aaSToby Isaac }
557878b19aaSToby Isaac 
558878b19aaSToby Isaac #undef __FUNCT__
5596dd5a8c8SToby Isaac #define __FUNCT__ "AnchorsFlatten"
5606dd5a8c8SToby Isaac static PetscErrorCode AnchorsFlatten (PetscSection section, IS is, PetscSection *sectionNew, IS *isNew)
5616dd5a8c8SToby Isaac {
5626dd5a8c8SToby Isaac   PetscInt       pStart, pEnd, size, sizeNew, i, p, *valsNew = NULL;
5636dd5a8c8SToby Isaac   const PetscInt *vals;
5646dd5a8c8SToby Isaac   PetscSection   secNew;
5656dd5a8c8SToby Isaac   PetscBool      anyNew, globalAnyNew;
5666dd5a8c8SToby Isaac   PetscBool      compress;
5676dd5a8c8SToby Isaac   PetscErrorCode ierr;
5686dd5a8c8SToby Isaac 
5696dd5a8c8SToby Isaac   PetscFunctionBegin;
5706dd5a8c8SToby Isaac   ierr = PetscSectionGetChart(section,&pStart,&pEnd);CHKERRQ(ierr);
5716dd5a8c8SToby Isaac   ierr = ISGetLocalSize(is,&size);CHKERRQ(ierr);
5726dd5a8c8SToby Isaac   ierr = ISGetIndices(is,&vals);CHKERRQ(ierr);
5736dd5a8c8SToby Isaac   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secNew);CHKERRQ(ierr);
5746dd5a8c8SToby Isaac   ierr = PetscSectionSetChart(secNew,pStart,pEnd);CHKERRQ(ierr);
5756dd5a8c8SToby Isaac   for (i = 0; i < size; i++) {
5766dd5a8c8SToby Isaac     PetscInt dof;
5776dd5a8c8SToby Isaac 
5786dd5a8c8SToby Isaac     p = vals[i];
5796dd5a8c8SToby Isaac     if (p < pStart || p >= pEnd) continue;
5806dd5a8c8SToby Isaac     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
5816dd5a8c8SToby Isaac     if (dof) break;
5826dd5a8c8SToby Isaac   }
5836dd5a8c8SToby Isaac   if (i == size) {
5846dd5a8c8SToby Isaac     ierr     = PetscSectionSetUp(secNew);CHKERRQ(ierr);
5856dd5a8c8SToby Isaac     anyNew   = PETSC_FALSE;
5866dd5a8c8SToby Isaac     compress = PETSC_FALSE;
5876dd5a8c8SToby Isaac     sizeNew  = 0;
5886dd5a8c8SToby Isaac   }
5896dd5a8c8SToby Isaac   else {
5906dd5a8c8SToby Isaac     anyNew = PETSC_TRUE;
5916dd5a8c8SToby Isaac     for (p = pStart; p < pEnd; p++) {
5926dd5a8c8SToby Isaac       PetscInt dof, off;
5936dd5a8c8SToby Isaac 
5946dd5a8c8SToby Isaac       ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
5956dd5a8c8SToby Isaac       ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
5966dd5a8c8SToby Isaac       for (i = 0; i < dof; i++) {
5976dd5a8c8SToby Isaac         PetscInt q = vals[off + i], qDof = 0;
5986dd5a8c8SToby Isaac 
5996dd5a8c8SToby Isaac         if (q >= pStart && q < pEnd) {
6006dd5a8c8SToby Isaac           ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr);
6016dd5a8c8SToby Isaac         }
6026dd5a8c8SToby Isaac         if (qDof) {
6036dd5a8c8SToby Isaac           ierr = PetscSectionAddDof(secNew, p, qDof);CHKERRQ(ierr);
6046dd5a8c8SToby Isaac         }
6056dd5a8c8SToby Isaac         else {
6066dd5a8c8SToby Isaac           ierr = PetscSectionAddDof(secNew, p, 1);CHKERRQ(ierr);
6076dd5a8c8SToby Isaac         }
6086dd5a8c8SToby Isaac       }
6096dd5a8c8SToby Isaac     }
6106dd5a8c8SToby Isaac     ierr = PetscSectionSetUp(secNew);CHKERRQ(ierr);
6116dd5a8c8SToby Isaac     ierr = PetscSectionGetStorageSize(secNew,&sizeNew);CHKERRQ(ierr);
6126dd5a8c8SToby Isaac     ierr = PetscMalloc1(sizeNew,&valsNew);CHKERRQ(ierr);
6136dd5a8c8SToby Isaac     compress = PETSC_FALSE;
6146dd5a8c8SToby Isaac     for (p = pStart; p < pEnd; p++) {
6156dd5a8c8SToby Isaac       PetscInt dof, off, count, offNew, dofNew;
6166dd5a8c8SToby Isaac 
6176dd5a8c8SToby Isaac       ierr  = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
6186dd5a8c8SToby Isaac       ierr  = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
6196dd5a8c8SToby Isaac       ierr  = PetscSectionGetDof(secNew, p, &dofNew);CHKERRQ(ierr);
6206dd5a8c8SToby Isaac       ierr  = PetscSectionGetOffset(secNew, p, &offNew);CHKERRQ(ierr);
6216dd5a8c8SToby Isaac       count = 0;
6226dd5a8c8SToby Isaac       for (i = 0; i < dof; i++) {
6236dd5a8c8SToby Isaac         PetscInt q = vals[off + i], qDof = 0, qOff = 0, j;
6246dd5a8c8SToby Isaac 
6256dd5a8c8SToby Isaac         if (q >= pStart && q < pEnd) {
6266dd5a8c8SToby Isaac           ierr = PetscSectionGetDof(section, q, &qDof);CHKERRQ(ierr);
6276dd5a8c8SToby Isaac           ierr = PetscSectionGetOffset(section, q, &qOff);CHKERRQ(ierr);
6286dd5a8c8SToby Isaac         }
6296dd5a8c8SToby Isaac         if (qDof) {
6306dd5a8c8SToby Isaac           PetscInt oldCount = count;
6316dd5a8c8SToby Isaac 
6326dd5a8c8SToby Isaac           for (j = 0; j < qDof; j++) {
6336dd5a8c8SToby Isaac             PetscInt k, r = vals[qOff + j];
6346dd5a8c8SToby Isaac 
6356dd5a8c8SToby Isaac             for (k = 0; k < oldCount; k++) {
6366dd5a8c8SToby Isaac               if (valsNew[offNew + k] == r) {
6376dd5a8c8SToby Isaac                 break;
6386dd5a8c8SToby Isaac               }
6396dd5a8c8SToby Isaac             }
6406dd5a8c8SToby Isaac             if (k == oldCount) {
6416dd5a8c8SToby Isaac               valsNew[offNew + count++] = r;
6426dd5a8c8SToby Isaac             }
6436dd5a8c8SToby Isaac           }
6446dd5a8c8SToby Isaac         }
6456dd5a8c8SToby Isaac         else {
6466dd5a8c8SToby Isaac           PetscInt k, oldCount = count;
6476dd5a8c8SToby Isaac 
6486dd5a8c8SToby Isaac           for (k = 0; k < oldCount; k++) {
6496dd5a8c8SToby Isaac             if (valsNew[offNew + k] == q) {
6506dd5a8c8SToby Isaac               break;
6516dd5a8c8SToby Isaac             }
6526dd5a8c8SToby Isaac           }
6536dd5a8c8SToby Isaac           if (k == oldCount) {
6546dd5a8c8SToby Isaac             valsNew[offNew + count++] = q;
6556dd5a8c8SToby Isaac           }
6566dd5a8c8SToby Isaac         }
6576dd5a8c8SToby Isaac       }
6586dd5a8c8SToby Isaac       if (count < dofNew) {
6596dd5a8c8SToby Isaac         ierr = PetscSectionSetDof(secNew, p, count);CHKERRQ(ierr);
6606dd5a8c8SToby Isaac         compress = PETSC_TRUE;
6616dd5a8c8SToby Isaac       }
6626dd5a8c8SToby Isaac     }
6636dd5a8c8SToby Isaac   }
6646dd5a8c8SToby Isaac   ierr = ISRestoreIndices(is,&vals);CHKERRQ(ierr);
665b2566f29SBarry Smith   ierr = MPIU_Allreduce(&anyNew,&globalAnyNew,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRQ(ierr);
6666dd5a8c8SToby Isaac   if (!globalAnyNew) {
6676dd5a8c8SToby Isaac     ierr = PetscSectionDestroy(&secNew);CHKERRQ(ierr);
6686dd5a8c8SToby Isaac     *sectionNew = NULL;
6696dd5a8c8SToby Isaac     *isNew = NULL;
6706dd5a8c8SToby Isaac   }
6716dd5a8c8SToby Isaac   else {
6726dd5a8c8SToby Isaac     PetscBool globalCompress;
6736dd5a8c8SToby Isaac 
674b2566f29SBarry Smith     ierr = MPIU_Allreduce(&compress,&globalCompress,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)secNew));CHKERRQ(ierr);
6756dd5a8c8SToby Isaac     if (compress) {
6766dd5a8c8SToby Isaac       PetscSection secComp;
6776dd5a8c8SToby Isaac       PetscInt *valsComp = NULL;
6786dd5a8c8SToby Isaac 
6796dd5a8c8SToby Isaac       ierr = PetscSectionCreate(PetscObjectComm((PetscObject)section),&secComp);CHKERRQ(ierr);
6806dd5a8c8SToby Isaac       ierr = PetscSectionSetChart(secComp,pStart,pEnd);CHKERRQ(ierr);
6816dd5a8c8SToby Isaac       for (p = pStart; p < pEnd; p++) {
6826dd5a8c8SToby Isaac         PetscInt dof;
6836dd5a8c8SToby Isaac 
6846dd5a8c8SToby Isaac         ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr);
6856dd5a8c8SToby Isaac         ierr = PetscSectionSetDof(secComp, p, dof);CHKERRQ(ierr);
6866dd5a8c8SToby Isaac       }
6876dd5a8c8SToby Isaac       ierr = PetscSectionSetUp(secComp);CHKERRQ(ierr);
6886dd5a8c8SToby Isaac       ierr = PetscSectionGetStorageSize(secComp,&sizeNew);CHKERRQ(ierr);
6896dd5a8c8SToby Isaac       ierr = PetscMalloc1(sizeNew,&valsComp);CHKERRQ(ierr);
6906dd5a8c8SToby Isaac       for (p = pStart; p < pEnd; p++) {
6916dd5a8c8SToby Isaac         PetscInt dof, off, offNew, j;
6926dd5a8c8SToby Isaac 
6936dd5a8c8SToby Isaac         ierr = PetscSectionGetDof(secNew, p, &dof);CHKERRQ(ierr);
6946dd5a8c8SToby Isaac         ierr = PetscSectionGetOffset(secNew, p, &off);CHKERRQ(ierr);
6956dd5a8c8SToby Isaac         ierr = PetscSectionGetOffset(secComp, p, &offNew);CHKERRQ(ierr);
6966dd5a8c8SToby Isaac         for (j = 0; j < dof; j++) {
6976dd5a8c8SToby Isaac           valsComp[offNew + j] = valsNew[off + j];
6986dd5a8c8SToby Isaac         }
6996dd5a8c8SToby Isaac       }
7006dd5a8c8SToby Isaac       ierr    = PetscSectionDestroy(&secNew);CHKERRQ(ierr);
7016dd5a8c8SToby Isaac       secNew  = secComp;
7026dd5a8c8SToby Isaac       ierr    = PetscFree(valsNew);CHKERRQ(ierr);
7036dd5a8c8SToby Isaac       valsNew = valsComp;
7046dd5a8c8SToby Isaac     }
7056dd5a8c8SToby Isaac     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),sizeNew,valsNew,PETSC_OWN_POINTER,isNew);CHKERRQ(ierr);
7066dd5a8c8SToby Isaac   }
7076dd5a8c8SToby Isaac   PetscFunctionReturn(0);
7086dd5a8c8SToby Isaac }
7096dd5a8c8SToby Isaac 
7106dd5a8c8SToby Isaac #undef __FUNCT__
711f7c74593SToby Isaac #define __FUNCT__ "DMPlexCreateAnchors_Tree"
712f7c74593SToby Isaac static PetscErrorCode DMPlexCreateAnchors_Tree(DM dm)
71366af876cSToby Isaac {
71466af876cSToby Isaac   PetscInt       p, pStart, pEnd, *anchors, size;
71566af876cSToby Isaac   PetscInt       aMin = PETSC_MAX_INT, aMax = PETSC_MIN_INT;
71666af876cSToby Isaac   PetscSection   aSec;
717f9f063d4SToby Isaac   DMLabel        canonLabel;
71866af876cSToby Isaac   IS             aIS;
71966af876cSToby Isaac   PetscErrorCode ierr;
72066af876cSToby Isaac 
72166af876cSToby Isaac   PetscFunctionBegin;
72266af876cSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
72366af876cSToby Isaac   ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr);
724c58f1c22SToby Isaac   ierr = DMGetLabel(dm,"canonical",&canonLabel);CHKERRQ(ierr);
72566af876cSToby Isaac   for (p = pStart; p < pEnd; p++) {
72666af876cSToby Isaac     PetscInt parent;
72766af876cSToby Isaac 
728f9f063d4SToby Isaac     if (canonLabel) {
729f9f063d4SToby Isaac       PetscInt canon;
730f9f063d4SToby Isaac 
731f9f063d4SToby Isaac       ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr);
732f9f063d4SToby Isaac       if (p != canon) continue;
733f9f063d4SToby Isaac     }
73466af876cSToby Isaac     ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr);
73566af876cSToby Isaac     if (parent != p) {
73666af876cSToby Isaac       aMin = PetscMin(aMin,p);
73766af876cSToby Isaac       aMax = PetscMax(aMax,p+1);
73866af876cSToby Isaac     }
73966af876cSToby Isaac   }
74066af876cSToby Isaac   if (aMin > aMax) {
74166af876cSToby Isaac     aMin = -1;
74266af876cSToby Isaac     aMax = -1;
74366af876cSToby Isaac   }
744e228b242SToby Isaac   ierr = PetscSectionCreate(PETSC_COMM_SELF,&aSec);CHKERRQ(ierr);
74566af876cSToby Isaac   ierr = PetscSectionSetChart(aSec,aMin,aMax);CHKERRQ(ierr);
74666af876cSToby Isaac   for (p = aMin; p < aMax; p++) {
74766af876cSToby Isaac     PetscInt parent, ancestor = p;
74866af876cSToby Isaac 
749f9f063d4SToby Isaac     if (canonLabel) {
750f9f063d4SToby Isaac       PetscInt canon;
751f9f063d4SToby Isaac 
752f9f063d4SToby Isaac       ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr);
753f9f063d4SToby Isaac       if (p != canon) continue;
754f9f063d4SToby Isaac     }
75566af876cSToby Isaac     ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr);
75666af876cSToby Isaac     while (parent != ancestor) {
75766af876cSToby Isaac       ancestor = parent;
75866af876cSToby Isaac       ierr     = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr);
75966af876cSToby Isaac     }
76066af876cSToby Isaac     if (ancestor != p) {
76166af876cSToby Isaac       PetscInt closureSize, *closure = NULL;
76266af876cSToby Isaac 
76366af876cSToby Isaac       ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
76466af876cSToby Isaac       ierr = PetscSectionSetDof(aSec,p,closureSize);CHKERRQ(ierr);
76566af876cSToby Isaac       ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
76666af876cSToby Isaac     }
76766af876cSToby Isaac   }
76866af876cSToby Isaac   ierr = PetscSectionSetUp(aSec);CHKERRQ(ierr);
76966af876cSToby Isaac   ierr = PetscSectionGetStorageSize(aSec,&size);CHKERRQ(ierr);
77066af876cSToby Isaac   ierr = PetscMalloc1(size,&anchors);CHKERRQ(ierr);
77166af876cSToby Isaac   for (p = aMin; p < aMax; p++) {
77266af876cSToby Isaac     PetscInt parent, ancestor = p;
77366af876cSToby Isaac 
774f9f063d4SToby Isaac     if (canonLabel) {
775f9f063d4SToby Isaac       PetscInt canon;
776f9f063d4SToby Isaac 
777f9f063d4SToby Isaac       ierr = DMLabelGetValue(canonLabel,p,&canon);CHKERRQ(ierr);
778f9f063d4SToby Isaac       if (p != canon) continue;
779f9f063d4SToby Isaac     }
78066af876cSToby Isaac     ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr);
78166af876cSToby Isaac     while (parent != ancestor) {
78266af876cSToby Isaac       ancestor = parent;
78366af876cSToby Isaac       ierr     = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr);
78466af876cSToby Isaac     }
78566af876cSToby Isaac     if (ancestor != p) {
78666af876cSToby Isaac       PetscInt j, closureSize, *closure = NULL, aOff;
78766af876cSToby Isaac 
78866af876cSToby Isaac       ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr);
78966af876cSToby Isaac 
79066af876cSToby Isaac       ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
79166af876cSToby Isaac       for (j = 0; j < closureSize; j++) {
79266af876cSToby Isaac         anchors[aOff + j] = closure[2*j];
79366af876cSToby Isaac       }
79466af876cSToby Isaac       ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
79566af876cSToby Isaac     }
79666af876cSToby Isaac   }
797e228b242SToby Isaac   ierr = ISCreateGeneral(PETSC_COMM_SELF,size,anchors,PETSC_OWN_POINTER,&aIS);CHKERRQ(ierr);
7986dd5a8c8SToby Isaac   {
7996dd5a8c8SToby Isaac     PetscSection aSecNew = aSec;
8006dd5a8c8SToby Isaac     IS           aISNew  = aIS;
8016dd5a8c8SToby Isaac 
8026dd5a8c8SToby Isaac     ierr = PetscObjectReference((PetscObject)aSec);CHKERRQ(ierr);
8036dd5a8c8SToby Isaac     ierr = PetscObjectReference((PetscObject)aIS);CHKERRQ(ierr);
8046dd5a8c8SToby Isaac     while (aSecNew) {
8056dd5a8c8SToby Isaac       ierr    = PetscSectionDestroy(&aSec);CHKERRQ(ierr);
8066dd5a8c8SToby Isaac       ierr    = ISDestroy(&aIS);CHKERRQ(ierr);
8076dd5a8c8SToby Isaac       aSec    = aSecNew;
8086dd5a8c8SToby Isaac       aIS     = aISNew;
8096dd5a8c8SToby Isaac       aSecNew = NULL;
8106dd5a8c8SToby Isaac       aISNew  = NULL;
8116dd5a8c8SToby Isaac       ierr    = AnchorsFlatten(aSec,aIS,&aSecNew,&aISNew);CHKERRQ(ierr);
8126dd5a8c8SToby Isaac     }
8136dd5a8c8SToby Isaac   }
814a17985deSToby Isaac   ierr = DMPlexSetAnchors(dm,aSec,aIS);CHKERRQ(ierr);
81566af876cSToby Isaac   ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr);
81666af876cSToby Isaac   ierr = ISDestroy(&aIS);CHKERRQ(ierr);
81766af876cSToby Isaac   PetscFunctionReturn(0);
81866af876cSToby Isaac }
81966af876cSToby Isaac 
82066af876cSToby Isaac #undef __FUNCT__
8216461c1adSToby Isaac #define __FUNCT__ "DMPlexGetTrueSupportSize"
8226461c1adSToby Isaac static PetscErrorCode DMPlexGetTrueSupportSize(DM dm,PetscInt p,PetscInt *dof,PetscInt *numTrueSupp)
8236461c1adSToby Isaac {
8246461c1adSToby Isaac   PetscErrorCode ierr;
8256461c1adSToby Isaac 
8266461c1adSToby Isaac   PetscFunctionBegin;
8276461c1adSToby Isaac   if (numTrueSupp[p] == -1) {
8286461c1adSToby Isaac     PetscInt i, alldof;
8296461c1adSToby Isaac     const PetscInt *supp;
8306461c1adSToby Isaac     PetscInt count = 0;
8316461c1adSToby Isaac 
8326461c1adSToby Isaac     ierr = DMPlexGetSupportSize(dm,p,&alldof);CHKERRQ(ierr);
8336461c1adSToby Isaac     ierr = DMPlexGetSupport(dm,p,&supp);CHKERRQ(ierr);
8346461c1adSToby Isaac     for (i = 0; i < alldof; i++) {
8356461c1adSToby Isaac       PetscInt q = supp[i], numCones, j;
8366461c1adSToby Isaac       const PetscInt *cone;
8376461c1adSToby Isaac 
8386461c1adSToby Isaac       ierr = DMPlexGetConeSize(dm,q,&numCones);CHKERRQ(ierr);
8396461c1adSToby Isaac       ierr = DMPlexGetCone(dm,q,&cone);CHKERRQ(ierr);
8406461c1adSToby Isaac       for (j = 0; j < numCones; j++) {
8416461c1adSToby Isaac         if (cone[j] == p) break;
8426461c1adSToby Isaac       }
8436461c1adSToby Isaac       if (j < numCones) count++;
8446461c1adSToby Isaac     }
8456461c1adSToby Isaac     numTrueSupp[p] = count;
8466461c1adSToby Isaac   }
8476461c1adSToby Isaac   *dof = numTrueSupp[p];
8486461c1adSToby Isaac   PetscFunctionReturn(0);
8496461c1adSToby Isaac }
8506461c1adSToby Isaac 
8516461c1adSToby Isaac #undef __FUNCT__
852776742edSToby Isaac #define __FUNCT__ "DMPlexTreeExchangeSupports"
853776742edSToby Isaac static PetscErrorCode DMPlexTreeExchangeSupports(DM dm)
854776742edSToby Isaac {
855776742edSToby Isaac   DM_Plex *mesh = (DM_Plex *)dm->data;
856776742edSToby Isaac   PetscSection newSupportSection;
857776742edSToby Isaac   PetscInt newSize, *newSupports, pStart, pEnd, p, d, depth;
8586461c1adSToby Isaac   PetscInt *numTrueSupp;
859776742edSToby Isaac   PetscInt *offsets;
860776742edSToby Isaac   PetscErrorCode ierr;
861776742edSToby Isaac 
862776742edSToby Isaac   PetscFunctionBegin;
863776742edSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
864776742edSToby Isaac   /* symmetrize the hierarchy */
865776742edSToby Isaac   ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr);
866e228b242SToby Isaac   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)(mesh->supportSection)),&newSupportSection);CHKERRQ(ierr);
867776742edSToby Isaac   ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr);
868776742edSToby Isaac   ierr = PetscSectionSetChart(newSupportSection,pStart,pEnd);CHKERRQ(ierr);
869776742edSToby Isaac   ierr = PetscCalloc1(pEnd,&offsets);CHKERRQ(ierr);
8706461c1adSToby Isaac   ierr = PetscMalloc1(pEnd,&numTrueSupp);CHKERRQ(ierr);
8716461c1adSToby Isaac   for (p = 0; p < pEnd; p++) numTrueSupp[p] = -1;
8726461c1adSToby Isaac   /* if a point is in the (true) support of q, it should be in the support of
873776742edSToby Isaac    * parent(q) */
874776742edSToby Isaac   for (d = 0; d <= depth; d++) {
875776742edSToby Isaac     ierr = DMPlexGetHeightStratum(dm,d,&pStart,&pEnd);CHKERRQ(ierr);
876776742edSToby Isaac     for (p = pStart; p < pEnd; ++p) {
877776742edSToby Isaac       PetscInt dof, q, qdof, parent;
878776742edSToby Isaac 
8796461c1adSToby Isaac       ierr = DMPlexGetTrueSupportSize(dm,p,&dof,numTrueSupp);CHKERRQ(ierr);
880776742edSToby Isaac       ierr = PetscSectionAddDof(newSupportSection, p, dof);CHKERRQ(ierr);
881776742edSToby Isaac       q    = p;
882776742edSToby Isaac       ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr);
883776742edSToby Isaac       while (parent != q && parent >= pStart && parent < pEnd) {
884776742edSToby Isaac         q = parent;
885776742edSToby Isaac 
8866461c1adSToby Isaac         ierr = DMPlexGetTrueSupportSize(dm,q,&qdof,numTrueSupp);CHKERRQ(ierr);
887776742edSToby Isaac         ierr = PetscSectionAddDof(newSupportSection,p,qdof);CHKERRQ(ierr);
888776742edSToby Isaac         ierr = PetscSectionAddDof(newSupportSection,q,dof);CHKERRQ(ierr);
889776742edSToby Isaac         ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr);
890776742edSToby Isaac       }
891776742edSToby Isaac     }
892776742edSToby Isaac   }
893776742edSToby Isaac   ierr = PetscSectionSetUp(newSupportSection);CHKERRQ(ierr);
894776742edSToby Isaac   ierr = PetscSectionGetStorageSize(newSupportSection,&newSize);CHKERRQ(ierr);
895776742edSToby Isaac   ierr = PetscMalloc1(newSize,&newSupports);CHKERRQ(ierr);
896776742edSToby Isaac   for (d = 0; d <= depth; d++) {
897776742edSToby Isaac     ierr = DMPlexGetHeightStratum(dm,d,&pStart,&pEnd);CHKERRQ(ierr);
898776742edSToby Isaac     for (p = pStart; p < pEnd; p++) {
899776742edSToby Isaac       PetscInt dof, off, q, qdof, qoff, newDof, newOff, newqOff, i, parent;
900776742edSToby Isaac 
901776742edSToby Isaac       ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
902776742edSToby Isaac       ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
903776742edSToby Isaac       ierr = PetscSectionGetDof(newSupportSection, p, &newDof);CHKERRQ(ierr);
904776742edSToby Isaac       ierr = PetscSectionGetOffset(newSupportSection, p, &newOff);CHKERRQ(ierr);
905776742edSToby Isaac       for (i = 0; i < dof; i++) {
9066461c1adSToby Isaac         PetscInt numCones, j;
9076461c1adSToby Isaac         const PetscInt *cone;
9086461c1adSToby Isaac         PetscInt q = mesh->supports[off + i];
9096461c1adSToby Isaac 
9106461c1adSToby Isaac         ierr = DMPlexGetConeSize(dm,q,&numCones);CHKERRQ(ierr);
9116461c1adSToby Isaac         ierr = DMPlexGetCone(dm,q,&cone);CHKERRQ(ierr);
9126461c1adSToby Isaac         for (j = 0; j < numCones; j++) {
9136461c1adSToby Isaac           if (cone[j] == p) break;
9146461c1adSToby Isaac         }
9156461c1adSToby Isaac         if (j < numCones) newSupports[newOff+offsets[p]++] = q;
916776742edSToby Isaac       }
917776742edSToby Isaac       mesh->maxSupportSize = PetscMax(mesh->maxSupportSize,newDof);
918776742edSToby Isaac 
919776742edSToby Isaac       q    = p;
920776742edSToby Isaac       ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr);
921776742edSToby Isaac       while (parent != q && parent >= pStart && parent < pEnd) {
922776742edSToby Isaac         q = parent;
923776742edSToby Isaac         ierr = PetscSectionGetDof(mesh->supportSection, q, &qdof);CHKERRQ(ierr);
924776742edSToby Isaac         ierr = PetscSectionGetOffset(mesh->supportSection, q, &qoff);CHKERRQ(ierr);
925776742edSToby Isaac         ierr = PetscSectionGetOffset(newSupportSection, q, &newqOff);CHKERRQ(ierr);
926776742edSToby Isaac         for (i = 0; i < qdof; i++) {
9276461c1adSToby Isaac           PetscInt numCones, j;
9286461c1adSToby Isaac           const PetscInt *cone;
9296461c1adSToby Isaac           PetscInt r = mesh->supports[qoff + i];
9306461c1adSToby Isaac 
9316461c1adSToby Isaac           ierr = DMPlexGetConeSize(dm,r,&numCones);CHKERRQ(ierr);
9326461c1adSToby Isaac           ierr = DMPlexGetCone(dm,r,&cone);CHKERRQ(ierr);
9336461c1adSToby Isaac           for (j = 0; j < numCones; j++) {
9346461c1adSToby Isaac             if (cone[j] == q) break;
9356461c1adSToby Isaac           }
9366461c1adSToby Isaac           if (j < numCones) newSupports[newOff+offsets[p]++] = r;
937776742edSToby Isaac         }
938776742edSToby Isaac         for (i = 0; i < dof; i++) {
9396461c1adSToby Isaac           PetscInt numCones, j;
9406461c1adSToby Isaac           const PetscInt *cone;
9416461c1adSToby Isaac           PetscInt r = mesh->supports[off + i];
9426461c1adSToby Isaac 
9436461c1adSToby Isaac           ierr = DMPlexGetConeSize(dm,r,&numCones);CHKERRQ(ierr);
9446461c1adSToby Isaac           ierr = DMPlexGetCone(dm,r,&cone);CHKERRQ(ierr);
9456461c1adSToby Isaac           for (j = 0; j < numCones; j++) {
9466461c1adSToby Isaac             if (cone[j] == p) break;
9476461c1adSToby Isaac           }
9486461c1adSToby Isaac           if (j < numCones) newSupports[newqOff+offsets[q]++] = r;
949776742edSToby Isaac         }
950776742edSToby Isaac         ierr = DMPlexGetTreeParent(dm,q,&parent,NULL);CHKERRQ(ierr);
951776742edSToby Isaac       }
952776742edSToby Isaac     }
953776742edSToby Isaac   }
954776742edSToby Isaac   ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr);
955776742edSToby Isaac   mesh->supportSection = newSupportSection;
956776742edSToby Isaac   ierr = PetscFree(mesh->supports);CHKERRQ(ierr);
957776742edSToby Isaac   mesh->supports = newSupports;
958776742edSToby Isaac   ierr = PetscFree(offsets);CHKERRQ(ierr);
9596461c1adSToby Isaac   ierr = PetscFree(numTrueSupp);CHKERRQ(ierr);
960776742edSToby Isaac 
961776742edSToby Isaac   PetscFunctionReturn(0);
962776742edSToby Isaac }
963776742edSToby Isaac 
964f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM,PetscSection,PetscSection,Mat);
965f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM,PetscSection,PetscSection,Mat);
966f7c74593SToby Isaac 
967776742edSToby Isaac #undef __FUNCT__
968f9f063d4SToby Isaac #define __FUNCT__ "DMPlexSetTree_Internal"
969776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM dm, PetscSection parentSection, PetscInt *parents, PetscInt *childIDs, PetscBool computeCanonical, PetscBool exchangeSupports)
970f9f063d4SToby Isaac {
971f9f063d4SToby Isaac   DM_Plex       *mesh = (DM_Plex *)dm->data;
972f9f063d4SToby Isaac   DM             refTree;
973f9f063d4SToby Isaac   PetscInt       size;
974f9f063d4SToby Isaac   PetscErrorCode ierr;
975f9f063d4SToby Isaac 
976f9f063d4SToby Isaac   PetscFunctionBegin;
977f9f063d4SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
978f9f063d4SToby Isaac   PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2);
979f9f063d4SToby Isaac   ierr = PetscObjectReference((PetscObject)parentSection);CHKERRQ(ierr);
980f9f063d4SToby Isaac   ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr);
981f9f063d4SToby Isaac   mesh->parentSection = parentSection;
982f9f063d4SToby Isaac   ierr = PetscSectionGetStorageSize(parentSection,&size);CHKERRQ(ierr);
983f9f063d4SToby Isaac   if (parents != mesh->parents) {
984f9f063d4SToby Isaac     ierr = PetscFree(mesh->parents);CHKERRQ(ierr);
985f9f063d4SToby Isaac     ierr = PetscMalloc1(size,&mesh->parents);CHKERRQ(ierr);
986f9f063d4SToby Isaac     ierr = PetscMemcpy(mesh->parents, parents, size * sizeof(*parents));CHKERRQ(ierr);
987f9f063d4SToby Isaac   }
988f9f063d4SToby Isaac   if (childIDs != mesh->childIDs) {
989f9f063d4SToby Isaac     ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr);
990f9f063d4SToby Isaac     ierr = PetscMalloc1(size,&mesh->childIDs);CHKERRQ(ierr);
991f9f063d4SToby Isaac     ierr = PetscMemcpy(mesh->childIDs, childIDs, size * sizeof(*childIDs));CHKERRQ(ierr);
992f9f063d4SToby Isaac   }
993f9f063d4SToby Isaac   ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr);
994f9f063d4SToby Isaac   if (refTree) {
995f9f063d4SToby Isaac     DMLabel canonLabel;
996f9f063d4SToby Isaac 
997c58f1c22SToby Isaac     ierr = DMGetLabel(refTree,"canonical",&canonLabel);CHKERRQ(ierr);
998f9f063d4SToby Isaac     if (canonLabel) {
999f9f063d4SToby Isaac       PetscInt i;
1000f9f063d4SToby Isaac 
1001f9f063d4SToby Isaac       for (i = 0; i < size; i++) {
1002f9f063d4SToby Isaac         PetscInt canon;
1003f9f063d4SToby Isaac         ierr = DMLabelGetValue(canonLabel, mesh->childIDs[i], &canon);CHKERRQ(ierr);
1004f9f063d4SToby Isaac         if (canon >= 0) {
1005f9f063d4SToby Isaac           mesh->childIDs[i] = canon;
1006f9f063d4SToby Isaac         }
1007f9f063d4SToby Isaac       }
1008f9f063d4SToby Isaac     }
1009f7c74593SToby Isaac     mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_FromReference;
1010f7c74593SToby Isaac   }
1011f7c74593SToby Isaac   else {
1012f7c74593SToby Isaac     mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_Direct;
1013f9f063d4SToby Isaac   }
1014f9f063d4SToby Isaac   ierr = DMPlexTreeSymmetrize(dm);CHKERRQ(ierr);
1015f9f063d4SToby Isaac   if (computeCanonical) {
1016f9f063d4SToby Isaac     PetscInt d, dim;
1017f9f063d4SToby Isaac 
1018f9f063d4SToby Isaac     /* add the canonical label */
101928f4b327SMatthew G. Knepley     ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1020c58f1c22SToby Isaac     ierr = DMCreateLabel(dm,"canonical");CHKERRQ(ierr);
1021f9f063d4SToby Isaac     for (d = 0; d <= dim; d++) {
1022f9f063d4SToby Isaac       PetscInt p, dStart, dEnd, canon = -1, cNumChildren;
1023f9f063d4SToby Isaac       const PetscInt *cChildren;
1024f9f063d4SToby Isaac 
1025f9f063d4SToby Isaac       ierr = DMPlexGetDepthStratum(dm,d,&dStart,&dEnd);CHKERRQ(ierr);
1026f9f063d4SToby Isaac       for (p = dStart; p < dEnd; p++) {
1027f9f063d4SToby Isaac         ierr = DMPlexGetTreeChildren(dm,p,&cNumChildren,&cChildren);CHKERRQ(ierr);
1028f9f063d4SToby Isaac         if (cNumChildren) {
1029f9f063d4SToby Isaac           canon = p;
1030f9f063d4SToby Isaac           break;
1031f9f063d4SToby Isaac         }
1032f9f063d4SToby Isaac       }
1033f9f063d4SToby Isaac       if (canon == -1) continue;
1034f9f063d4SToby Isaac       for (p = dStart; p < dEnd; p++) {
1035f9f063d4SToby Isaac         PetscInt numChildren, i;
1036f9f063d4SToby Isaac         const PetscInt *children;
1037f9f063d4SToby Isaac 
1038f9f063d4SToby Isaac         ierr = DMPlexGetTreeChildren(dm,p,&numChildren,&children);CHKERRQ(ierr);
1039f9f063d4SToby Isaac         if (numChildren) {
1040f9f063d4SToby Isaac           if (numChildren != cNumChildren) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"All parent points in a stratum should have the same number of children: %d != %d", numChildren, cNumChildren);
1041c58f1c22SToby Isaac           ierr = DMSetLabelValue(dm,"canonical",p,canon);CHKERRQ(ierr);
1042f9f063d4SToby Isaac           for (i = 0; i < numChildren; i++) {
1043c58f1c22SToby Isaac             ierr = DMSetLabelValue(dm,"canonical",children[i],cChildren[i]);CHKERRQ(ierr);
1044f9f063d4SToby Isaac           }
1045f9f063d4SToby Isaac         }
1046f9f063d4SToby Isaac       }
1047f9f063d4SToby Isaac     }
1048f9f063d4SToby Isaac   }
1049776742edSToby Isaac   if (exchangeSupports) {
1050776742edSToby Isaac     ierr = DMPlexTreeExchangeSupports(dm);CHKERRQ(ierr);
1051776742edSToby Isaac   }
1052f7c74593SToby Isaac   mesh->createanchors = DMPlexCreateAnchors_Tree;
1053f7c74593SToby Isaac   /* reset anchors */
1054f7c74593SToby Isaac   ierr = DMPlexSetAnchors(dm,NULL,NULL);CHKERRQ(ierr);
1055f9f063d4SToby Isaac   PetscFunctionReturn(0);
1056f9f063d4SToby Isaac }
1057f9f063d4SToby Isaac 
1058f9f063d4SToby Isaac #undef __FUNCT__
10590b7167a0SToby Isaac #define __FUNCT__ "DMPlexSetTree"
10600b7167a0SToby Isaac /*@
10610b7167a0SToby Isaac   DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points.  This routine also creates
10620b7167a0SToby Isaac   the point-to-point constraints determined by the tree: a point is constained to the points in the closure of its
10630b7167a0SToby Isaac   tree root.
10640b7167a0SToby Isaac 
10650b7167a0SToby Isaac   Collective on dm
10660b7167a0SToby Isaac 
10670b7167a0SToby Isaac   Input Parameters:
10680b7167a0SToby Isaac + dm - the DMPlex object
10690b7167a0SToby Isaac . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section
10700b7167a0SToby Isaac                   offset indexes the parent and childID list; the reference count of parentSection is incremented
10710b7167a0SToby Isaac . parents - a list of the point parents; copied, can be destroyed
10720b7167a0SToby Isaac - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then
10730b7167a0SToby Isaac              the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed
10740b7167a0SToby Isaac 
10750b7167a0SToby Isaac   Level: intermediate
10760b7167a0SToby Isaac 
1077a17985deSToby Isaac .seealso: DMPlexGetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren()
10780b7167a0SToby Isaac @*/
1079b2f41788SToby Isaac PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[])
10800b7167a0SToby Isaac {
10810b7167a0SToby Isaac   PetscErrorCode ierr;
10820b7167a0SToby Isaac 
10830b7167a0SToby Isaac   PetscFunctionBegin;
1084776742edSToby Isaac   ierr = DMPlexSetTree_Internal(dm,parentSection,parents,childIDs,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
10850b7167a0SToby Isaac   PetscFunctionReturn(0);
10860b7167a0SToby Isaac }
10870b7167a0SToby Isaac 
10880b7167a0SToby Isaac #undef __FUNCT__
1089b2f41788SToby Isaac #define __FUNCT__ "DMPlexGetTree"
1090b2f41788SToby Isaac /*@
1091b2f41788SToby Isaac   DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points.
1092b2f41788SToby Isaac   Collective on dm
1093b2f41788SToby Isaac 
1094b2f41788SToby Isaac   Input Parameters:
1095b2f41788SToby Isaac . dm - the DMPlex object
1096b2f41788SToby Isaac 
1097b2f41788SToby Isaac   Output Parameters:
1098b2f41788SToby Isaac + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section
1099b2f41788SToby Isaac                   offset indexes the parent and childID list
1100b2f41788SToby Isaac . parents - a list of the point parents
1101b2f41788SToby Isaac . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then
1102b2f41788SToby Isaac              the child corresponds to the point in the reference tree with index childID
1103b2f41788SToby Isaac . childSection - the inverse of the parent section
1104b2f41788SToby Isaac - children - a list of the point children
1105b2f41788SToby Isaac 
1106b2f41788SToby Isaac   Level: intermediate
1107b2f41788SToby Isaac 
1108a17985deSToby Isaac .seealso: DMPlexSetTree(), DMPlexSetReferenceTree(), DMPlexSetAnchors(), DMPlexGetTreeParent(), DMPlexGetTreeChildren()
1109b2f41788SToby Isaac @*/
1110b2f41788SToby Isaac PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[])
1111b2f41788SToby Isaac {
1112b2f41788SToby Isaac   DM_Plex        *mesh = (DM_Plex *)dm->data;
1113b2f41788SToby Isaac 
1114b2f41788SToby Isaac   PetscFunctionBegin;
1115b2f41788SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1116b2f41788SToby Isaac   if (parentSection) *parentSection = mesh->parentSection;
1117b2f41788SToby Isaac   if (parents)       *parents       = mesh->parents;
1118b2f41788SToby Isaac   if (childIDs)      *childIDs      = mesh->childIDs;
1119b2f41788SToby Isaac   if (childSection)  *childSection  = mesh->childSection;
1120b2f41788SToby Isaac   if (children)      *children      = mesh->children;
1121b2f41788SToby Isaac   PetscFunctionReturn(0);
1122b2f41788SToby Isaac }
1123b2f41788SToby Isaac 
1124b2f41788SToby Isaac #undef __FUNCT__
1125d961a43aSToby Isaac #define __FUNCT__ "DMPlexGetTreeParent"
1126d961a43aSToby Isaac /*@
1127d961a43aSToby Isaac   DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the Sieve DAG)
1128d961a43aSToby Isaac 
1129d961a43aSToby Isaac   Input Parameters:
1130d961a43aSToby Isaac + dm - the DMPlex object
1131d961a43aSToby Isaac - point - the query point
1132d961a43aSToby Isaac 
1133d961a43aSToby Isaac   Output Parameters:
1134d961a43aSToby Isaac + parent - if not NULL, set to the parent of the point, or the point itself if the point does not have a parent
1135d961a43aSToby Isaac - childID - if not NULL, set to the child ID of the point with respect to its parent, or 0 if the point
1136d961a43aSToby Isaac             does not have a parent
1137d961a43aSToby Isaac 
1138d961a43aSToby Isaac   Level: intermediate
1139d961a43aSToby Isaac 
1140d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeChildren()
1141d961a43aSToby Isaac @*/
1142d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID)
1143d961a43aSToby Isaac {
1144d961a43aSToby Isaac   DM_Plex       *mesh = (DM_Plex *)dm->data;
1145d961a43aSToby Isaac   PetscSection   pSec;
1146d961a43aSToby Isaac   PetscErrorCode ierr;
1147d961a43aSToby Isaac 
1148d961a43aSToby Isaac   PetscFunctionBegin;
1149d961a43aSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1150d961a43aSToby Isaac   pSec = mesh->parentSection;
1151d961a43aSToby Isaac   if (pSec && point >= pSec->pStart && point < pSec->pEnd) {
1152d961a43aSToby Isaac     PetscInt dof;
1153d961a43aSToby Isaac 
1154d961a43aSToby Isaac     ierr = PetscSectionGetDof (pSec, point, &dof);CHKERRQ(ierr);
1155d961a43aSToby Isaac     if (dof) {
1156d961a43aSToby Isaac       PetscInt off;
1157d961a43aSToby Isaac 
1158d961a43aSToby Isaac       ierr = PetscSectionGetOffset (pSec, point, &off);CHKERRQ(ierr);
1159d961a43aSToby Isaac       if (parent)  *parent = mesh->parents[off];
1160d961a43aSToby Isaac       if (childID) *childID = mesh->childIDs[off];
1161d961a43aSToby Isaac       PetscFunctionReturn(0);
1162d961a43aSToby Isaac     }
1163d961a43aSToby Isaac   }
1164d961a43aSToby Isaac   if (parent) {
1165d961a43aSToby Isaac     *parent = point;
1166d961a43aSToby Isaac   }
1167d961a43aSToby Isaac   if (childID) {
1168d961a43aSToby Isaac     *childID = 0;
1169d961a43aSToby Isaac   }
1170d961a43aSToby Isaac   PetscFunctionReturn(0);
1171d961a43aSToby Isaac }
1172d961a43aSToby Isaac 
1173d961a43aSToby Isaac #undef __FUNCT__
1174d961a43aSToby Isaac #define __FUNCT__ "DMPlexGetTreeChildren"
1175d961a43aSToby Isaac /*@C
1176d961a43aSToby Isaac   DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the Sieve DAG)
1177d961a43aSToby Isaac 
1178d961a43aSToby Isaac   Input Parameters:
1179d961a43aSToby Isaac + dm - the DMPlex object
1180d961a43aSToby Isaac - point - the query point
1181d961a43aSToby Isaac 
1182d961a43aSToby Isaac   Output Parameters:
1183d961a43aSToby Isaac + numChildren - if not NULL, set to the number of children
1184d961a43aSToby Isaac - children - if not NULL, set to a list children, or set to NULL if the point has no children
1185d961a43aSToby Isaac 
1186d961a43aSToby Isaac   Level: intermediate
1187d961a43aSToby Isaac 
1188d961a43aSToby Isaac   Fortran Notes:
1189d961a43aSToby Isaac   Since it returns an array, this routine is only available in Fortran 90, and you must
1190d961a43aSToby Isaac   include petsc.h90 in your code.
1191d961a43aSToby Isaac 
1192d961a43aSToby Isaac .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeParent()
1193d961a43aSToby Isaac @*/
1194d961a43aSToby Isaac PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[])
1195d961a43aSToby Isaac {
1196d961a43aSToby Isaac   DM_Plex       *mesh = (DM_Plex *)dm->data;
1197d961a43aSToby Isaac   PetscSection   childSec;
1198d961a43aSToby Isaac   PetscInt       dof = 0;
1199d961a43aSToby Isaac   PetscErrorCode ierr;
1200d961a43aSToby Isaac 
1201d961a43aSToby Isaac   PetscFunctionBegin;
1202d961a43aSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1203d961a43aSToby Isaac   childSec = mesh->childSection;
1204d961a43aSToby Isaac   if (childSec && point >= childSec->pStart && point < childSec->pEnd) {
1205d961a43aSToby Isaac     ierr = PetscSectionGetDof (childSec, point, &dof);CHKERRQ(ierr);
1206d961a43aSToby Isaac   }
1207d961a43aSToby Isaac   if (numChildren) *numChildren = dof;
1208d961a43aSToby Isaac   if (children) {
1209d961a43aSToby Isaac     if (dof) {
1210d961a43aSToby Isaac       PetscInt off;
1211d961a43aSToby Isaac 
1212d961a43aSToby Isaac       ierr = PetscSectionGetOffset (childSec, point, &off);CHKERRQ(ierr);
1213d961a43aSToby Isaac       *children = &mesh->children[off];
1214d961a43aSToby Isaac     }
1215d961a43aSToby Isaac     else {
1216d961a43aSToby Isaac       *children = NULL;
1217d961a43aSToby Isaac     }
1218d961a43aSToby Isaac   }
1219d961a43aSToby Isaac   PetscFunctionReturn(0);
1220d961a43aSToby Isaac }
12210c37af3bSToby Isaac 
12220c37af3bSToby Isaac #undef __FUNCT__
1223f7c74593SToby Isaac #define __FUNCT__ "DMPlexComputeAnchorMatrix_Tree_Direct"
1224f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM dm, PetscSection section, PetscSection cSec, Mat cMat)
12250c37af3bSToby Isaac {
12260c37af3bSToby Isaac   PetscDS        ds;
12270c37af3bSToby Isaac   PetscInt       spdim;
12280c37af3bSToby Isaac   PetscInt       numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd;
12290c37af3bSToby Isaac   const PetscInt *anchors;
1230f7c74593SToby Isaac   PetscSection   aSec;
12310c37af3bSToby Isaac   PetscReal      *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent;
12320c37af3bSToby Isaac   IS             aIS;
12330c37af3bSToby Isaac   PetscErrorCode ierr;
12340c37af3bSToby Isaac 
12350c37af3bSToby Isaac   PetscFunctionBegin;
12360c37af3bSToby Isaac   ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr);
12370c37af3bSToby Isaac   ierr = DMGetDS(dm,&ds);CHKERRQ(ierr);
12380c37af3bSToby Isaac   ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr);
12390c37af3bSToby Isaac   ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr);
1240a17985deSToby Isaac   ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr);
12410c37af3bSToby Isaac   ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr);
12420c37af3bSToby Isaac   ierr = PetscSectionGetChart(cSec,&conStart,&conEnd);CHKERRQ(ierr);
124328f4b327SMatthew G. Knepley   ierr = DMGetDimension(dm,&spdim);CHKERRQ(ierr);
12440c37af3bSToby Isaac   ierr = PetscMalloc6(spdim,&v0,spdim,&v0parent,spdim,&vtmp,spdim*spdim,&J,spdim*spdim,&Jparent,spdim*spdim,&invJparent);CHKERRQ(ierr);
12450c37af3bSToby Isaac 
12460c37af3bSToby Isaac   for (f = 0; f < numFields; f++) {
12470dd1b1feSToby Isaac     PetscObject disc;
12480dd1b1feSToby Isaac     PetscFE fe = NULL;
12490dd1b1feSToby Isaac     PetscFV fv = NULL;
12500dd1b1feSToby Isaac     PetscClassId id;
12510c37af3bSToby Isaac     PetscDualSpace space;
12520c37af3bSToby Isaac     PetscInt i, j, k, nPoints, offset;
12530c37af3bSToby Isaac     PetscInt fSize, fComp;
1254c111c6b7SMatthew G. Knepley     PetscReal *B = NULL;
12550c37af3bSToby Isaac     PetscReal *weights, *pointsRef, *pointsReal;
12560c37af3bSToby Isaac     Mat Amat, Bmat, Xmat;
12570c37af3bSToby Isaac 
12580dd1b1feSToby Isaac     ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr);
12590dd1b1feSToby Isaac     ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr);
12600dd1b1feSToby Isaac     if (id == PETSCFE_CLASSID) {
12610dd1b1feSToby Isaac       fe = (PetscFE) disc;
12620c37af3bSToby Isaac       ierr = PetscFEGetDualSpace(fe,&space);CHKERRQ(ierr);
12630c37af3bSToby Isaac       ierr = PetscDualSpaceGetDimension(space,&fSize);CHKERRQ(ierr);
12640c37af3bSToby Isaac       ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr);
12650dd1b1feSToby Isaac     }
12660dd1b1feSToby Isaac     else if (id == PETSCFV_CLASSID) {
12670dd1b1feSToby Isaac       fv = (PetscFV) disc;
12680dd1b1feSToby Isaac       ierr = PetscFVGetDualSpace(fv,&space);CHKERRQ(ierr);
12690dd1b1feSToby Isaac       ierr = PetscDualSpaceGetDimension(space,&fSize);CHKERRQ(ierr);
12700dd1b1feSToby Isaac       ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr);
12710dd1b1feSToby Isaac     }
12720dd1b1feSToby Isaac     else SETERRQ1(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id);
12730dd1b1feSToby Isaac 
12740c37af3bSToby Isaac     ierr = MatCreate(PETSC_COMM_SELF,&Amat);CHKERRQ(ierr);
12750c37af3bSToby Isaac     ierr = MatSetSizes(Amat,fSize,fSize,fSize,fSize);CHKERRQ(ierr);
12760c37af3bSToby Isaac     ierr = MatSetType(Amat,MATSEQDENSE);CHKERRQ(ierr);
12770c37af3bSToby Isaac     ierr = MatSetUp(Amat);CHKERRQ(ierr);
12780c37af3bSToby Isaac     ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Bmat);CHKERRQ(ierr);
12790c37af3bSToby Isaac     ierr = MatDuplicate(Amat,MAT_DO_NOT_COPY_VALUES,&Xmat);CHKERRQ(ierr);
12800c37af3bSToby Isaac     nPoints = 0;
12810c37af3bSToby Isaac     for (i = 0; i < fSize; i++) {
12820c37af3bSToby Isaac       PetscInt        qPoints;
12830c37af3bSToby Isaac       PetscQuadrature quad;
12840c37af3bSToby Isaac 
12850c37af3bSToby Isaac       ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr);
12860c37af3bSToby Isaac       ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr);
12870c37af3bSToby Isaac       nPoints += qPoints;
12880c37af3bSToby Isaac     }
12890c37af3bSToby Isaac     ierr = PetscMalloc3(nPoints,&weights,spdim*nPoints,&pointsRef,spdim*nPoints,&pointsReal);CHKERRQ(ierr);
12900c37af3bSToby Isaac     offset = 0;
12910c37af3bSToby Isaac     for (i = 0; i < fSize; i++) {
12920c37af3bSToby Isaac       PetscInt        qPoints;
12930c37af3bSToby Isaac       const PetscReal    *p, *w;
12940c37af3bSToby Isaac       PetscQuadrature quad;
12950c37af3bSToby Isaac 
12960c37af3bSToby Isaac       ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr);
12970c37af3bSToby Isaac       ierr = PetscQuadratureGetData(quad,NULL,&qPoints,&p,&w);CHKERRQ(ierr);
12980c37af3bSToby Isaac       ierr = PetscMemcpy(weights+offset,w,qPoints*sizeof(*w));CHKERRQ(ierr);
12990c37af3bSToby Isaac       ierr = PetscMemcpy(pointsRef+spdim*offset,p,spdim*qPoints*sizeof(*p));CHKERRQ(ierr);
13000c37af3bSToby Isaac       offset += qPoints;
13010c37af3bSToby Isaac     }
13020dd1b1feSToby Isaac     if (id == PETSCFE_CLASSID) {
13030c37af3bSToby Isaac       ierr = PetscFEGetTabulation(fe,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr);
13040dd1b1feSToby Isaac     }
13050dd1b1feSToby Isaac     else {
13060dd1b1feSToby Isaac       ierr = PetscFVGetTabulation(fv,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr);
13070dd1b1feSToby Isaac     }
13080c37af3bSToby Isaac     offset = 0;
13090c37af3bSToby Isaac     for (i = 0; i < fSize; i++) {
13100c37af3bSToby Isaac       PetscInt        qPoints;
13110c37af3bSToby Isaac       PetscQuadrature quad;
13120c37af3bSToby Isaac 
13130c37af3bSToby Isaac       ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr);
13140c37af3bSToby Isaac       ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr);
13150c37af3bSToby Isaac       for (j = 0; j < fSize; j++) {
13160c37af3bSToby Isaac         PetscScalar val = 0.;
13170c37af3bSToby Isaac 
13180c37af3bSToby Isaac         for (k = 0; k < qPoints; k++) {
13190c37af3bSToby Isaac           val += B[((offset + k) * fSize + j) * fComp] * weights[k];
13200c37af3bSToby Isaac         }
13210c37af3bSToby Isaac         ierr = MatSetValue(Amat,i,j,val,INSERT_VALUES);CHKERRQ(ierr);
13220c37af3bSToby Isaac       }
13230c37af3bSToby Isaac       offset += qPoints;
13240c37af3bSToby Isaac     }
13250dd1b1feSToby Isaac     if (id == PETSCFE_CLASSID) {
13260c37af3bSToby Isaac       ierr = PetscFERestoreTabulation(fe,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr);
13270dd1b1feSToby Isaac     }
13280dd1b1feSToby Isaac     else {
13290dd1b1feSToby Isaac       ierr = PetscFVRestoreTabulation(fv,nPoints,pointsRef,&B,NULL,NULL);CHKERRQ(ierr);
13300dd1b1feSToby Isaac     }
13310c37af3bSToby Isaac     ierr = MatAssemblyBegin(Amat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13320c37af3bSToby Isaac     ierr = MatAssemblyEnd(Amat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13330c37af3bSToby Isaac     ierr = MatLUFactor(Amat,NULL,NULL,NULL);CHKERRQ(ierr);
13340c37af3bSToby Isaac     for (c = cStart; c < cEnd; c++) {
13350c37af3bSToby Isaac       PetscInt parent;
13360c37af3bSToby Isaac       PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL;
13370c37af3bSToby Isaac       PetscInt *childOffsets, *parentOffsets;
13380c37af3bSToby Isaac 
13390c37af3bSToby Isaac       ierr = DMPlexGetTreeParent(dm,c,&parent,NULL);CHKERRQ(ierr);
13400c37af3bSToby Isaac       if (parent == c) continue;
13410c37af3bSToby Isaac       ierr = DMPlexGetTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
13420c37af3bSToby Isaac       for (i = 0; i < closureSize; i++) {
13430c37af3bSToby Isaac         PetscInt p = closure[2*i];
13440c37af3bSToby Isaac         PetscInt conDof;
13450c37af3bSToby Isaac 
13460c37af3bSToby Isaac         if (p < conStart || p >= conEnd) continue;
13470c37af3bSToby Isaac         if (numFields > 1) {
13480c37af3bSToby Isaac           ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr);
13490c37af3bSToby Isaac         }
13500c37af3bSToby Isaac         else {
13510c37af3bSToby Isaac           ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr);
13520c37af3bSToby Isaac         }
13530c37af3bSToby Isaac         if (conDof) break;
13540c37af3bSToby Isaac       }
13550c37af3bSToby Isaac       if (i == closureSize) {
13560c37af3bSToby Isaac         ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
13570c37af3bSToby Isaac         continue;
13580c37af3bSToby Isaac       }
13590c37af3bSToby Isaac 
136073a7f2aaSMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr);
136173a7f2aaSMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dm, parent, NULL, v0parent, Jparent, invJparent, &detJparent);CHKERRQ(ierr);
13620c37af3bSToby Isaac       for (i = 0; i < nPoints; i++) {
13630c37af3bSToby Isaac         CoordinatesRefToReal(spdim, spdim, v0, J, &pointsRef[i*spdim],vtmp);CHKERRQ(ierr);
13640c37af3bSToby Isaac         CoordinatesRealToRef(spdim, spdim, v0parent, invJparent, vtmp, &pointsReal[i*spdim]);CHKERRQ(ierr);
13650c37af3bSToby Isaac       }
13660dd1b1feSToby Isaac       if (id == PETSCFE_CLASSID) {
13670c37af3bSToby Isaac         ierr = PetscFEGetTabulation(fe,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr);
13680dd1b1feSToby Isaac       }
13690dd1b1feSToby Isaac       else {
13700dd1b1feSToby Isaac         ierr = PetscFVGetTabulation(fv,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr);
13710dd1b1feSToby Isaac       }
13720c37af3bSToby Isaac       offset = 0;
13730c37af3bSToby Isaac       for (i = 0; i < fSize; i++) {
13740c37af3bSToby Isaac         PetscInt        qPoints;
13750c37af3bSToby Isaac         PetscQuadrature quad;
13760c37af3bSToby Isaac 
13770c37af3bSToby Isaac         ierr = PetscDualSpaceGetFunctional(space,i,&quad);CHKERRQ(ierr);
13780c37af3bSToby Isaac         ierr = PetscQuadratureGetData(quad,NULL,&qPoints,NULL,NULL);CHKERRQ(ierr);
13790c37af3bSToby Isaac         for (j = 0; j < fSize; j++) {
13800c37af3bSToby Isaac           PetscScalar val = 0.;
13810c37af3bSToby Isaac 
13820c37af3bSToby Isaac           for (k = 0; k < qPoints; k++) {
13830c37af3bSToby Isaac             val += B[((offset + k) * fSize + j) * fComp] * weights[k];
13840c37af3bSToby Isaac           }
13850c37af3bSToby Isaac           MatSetValue(Bmat,i,j,val,INSERT_VALUES);CHKERRQ(ierr);
13860c37af3bSToby Isaac         }
13870c37af3bSToby Isaac         offset += qPoints;
13880c37af3bSToby Isaac       }
13890dd1b1feSToby Isaac       if (id == PETSCFE_CLASSID) {
13900c37af3bSToby Isaac         ierr = PetscFERestoreTabulation(fe,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr);
13910dd1b1feSToby Isaac       }
13920dd1b1feSToby Isaac       else {
13930dd1b1feSToby Isaac         ierr = PetscFVRestoreTabulation(fv,nPoints,pointsReal,&B,NULL,NULL);CHKERRQ(ierr);
13940dd1b1feSToby Isaac       }
13950c37af3bSToby Isaac       ierr = MatAssemblyBegin(Bmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13960c37af3bSToby Isaac       ierr = MatAssemblyEnd(Bmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13970c37af3bSToby Isaac       ierr = MatMatSolve(Amat,Bmat,Xmat);CHKERRQ(ierr);
13980c37af3bSToby Isaac       ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP);CHKERRQ(ierr);
13990c37af3bSToby Isaac       ierr = PetscMalloc2(closureSize+1,&childOffsets,closureSizeP+1,&parentOffsets);CHKERRQ(ierr);
14000c37af3bSToby Isaac       childOffsets[0] = 0;
14010c37af3bSToby Isaac       for (i = 0; i < closureSize; i++) {
14020c37af3bSToby Isaac         PetscInt p = closure[2*i];
14030c37af3bSToby Isaac         PetscInt dof;
14040c37af3bSToby Isaac 
14050c37af3bSToby Isaac         if (numFields > 1) {
14060c37af3bSToby Isaac           ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr);
14070c37af3bSToby Isaac         }
14080c37af3bSToby Isaac         else {
14090c37af3bSToby Isaac           ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr);
14100c37af3bSToby Isaac         }
14110c37af3bSToby Isaac         childOffsets[i+1]=childOffsets[i]+dof / fComp;
14120c37af3bSToby Isaac       }
14130c37af3bSToby Isaac       parentOffsets[0] = 0;
14140c37af3bSToby Isaac       for (i = 0; i < closureSizeP; i++) {
14150c37af3bSToby Isaac         PetscInt p = closureP[2*i];
14160c37af3bSToby Isaac         PetscInt dof;
14170c37af3bSToby Isaac 
14180c37af3bSToby Isaac         if (numFields > 1) {
14190c37af3bSToby Isaac           ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr);
14200c37af3bSToby Isaac         }
14210c37af3bSToby Isaac         else {
14220c37af3bSToby Isaac           ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr);
14230c37af3bSToby Isaac         }
14240c37af3bSToby Isaac         parentOffsets[i+1]=parentOffsets[i]+dof / fComp;
14250c37af3bSToby Isaac       }
14260c37af3bSToby Isaac       for (i = 0; i < closureSize; i++) {
14270c37af3bSToby Isaac         PetscInt conDof, conOff, aDof, aOff;
14280c37af3bSToby Isaac         PetscInt p = closure[2*i];
14290c37af3bSToby Isaac         PetscInt o = closure[2*i+1];
14300c37af3bSToby Isaac 
14310c37af3bSToby Isaac         if (p < conStart || p >= conEnd) continue;
14320c37af3bSToby Isaac         if (numFields > 1) {
14330c37af3bSToby Isaac           ierr = PetscSectionGetFieldDof(cSec,p,f,&conDof);CHKERRQ(ierr);
14340c37af3bSToby Isaac           ierr = PetscSectionGetFieldOffset(cSec,p,f,&conOff);CHKERRQ(ierr);
14350c37af3bSToby Isaac         }
14360c37af3bSToby Isaac         else {
14370c37af3bSToby Isaac           ierr = PetscSectionGetDof(cSec,p,&conDof);CHKERRQ(ierr);
14380c37af3bSToby Isaac           ierr = PetscSectionGetOffset(cSec,p,&conOff);CHKERRQ(ierr);
14390c37af3bSToby Isaac         }
14400c37af3bSToby Isaac         if (!conDof) continue;
14410c37af3bSToby Isaac         ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr);
14420c37af3bSToby Isaac         ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr);
14430c37af3bSToby Isaac         for (k = 0; k < aDof; k++) {
14440c37af3bSToby Isaac           PetscInt a = anchors[aOff + k];
14450c37af3bSToby Isaac           PetscInt aSecDof, aSecOff;
14460c37af3bSToby Isaac 
14470c37af3bSToby Isaac           if (numFields > 1) {
14480c37af3bSToby Isaac             ierr = PetscSectionGetFieldDof(section,a,f,&aSecDof);CHKERRQ(ierr);
14490c37af3bSToby Isaac             ierr = PetscSectionGetFieldOffset(section,a,f,&aSecOff);CHKERRQ(ierr);
14500c37af3bSToby Isaac           }
14510c37af3bSToby Isaac           else {
14520c37af3bSToby Isaac             ierr = PetscSectionGetDof(section,a,&aSecDof);CHKERRQ(ierr);
14530c37af3bSToby Isaac             ierr = PetscSectionGetOffset(section,a,&aSecOff);CHKERRQ(ierr);
14540c37af3bSToby Isaac           }
14550c37af3bSToby Isaac           if (!aSecDof) continue;
14560c37af3bSToby Isaac 
14570c37af3bSToby Isaac           for (j = 0; j < closureSizeP; j++) {
14580c37af3bSToby Isaac             PetscInt q = closureP[2*j];
14590c37af3bSToby Isaac             PetscInt oq = closureP[2*j+1];
14600c37af3bSToby Isaac 
14610c37af3bSToby Isaac             if (q == a) {
14620c37af3bSToby Isaac               PetscInt r, s, t;
14630c37af3bSToby Isaac 
14640c37af3bSToby Isaac               for (r = childOffsets[i]; r < childOffsets[i+1]; r++) {
14650c37af3bSToby Isaac                 for (s = parentOffsets[j]; s < parentOffsets[j+1]; s++) {
14660c37af3bSToby Isaac                   PetscScalar val;
14670c37af3bSToby Isaac                   PetscInt insertCol, insertRow;
14680c37af3bSToby Isaac 
14690c37af3bSToby Isaac                   ierr = MatGetValue(Xmat,r,s,&val);CHKERRQ(ierr);
14700c37af3bSToby Isaac                   if (o >= 0) {
14710c37af3bSToby Isaac                     insertRow = conOff + fComp * (r - childOffsets[i]);
14720c37af3bSToby Isaac                   }
14730c37af3bSToby Isaac                   else {
14740c37af3bSToby Isaac                     insertRow = conOff + fComp * (childOffsets[i + 1] - 1 - r);
14750c37af3bSToby Isaac                   }
14760c37af3bSToby Isaac                   if (oq >= 0) {
14770c37af3bSToby Isaac                     insertCol = aSecOff + fComp * (s - parentOffsets[j]);
14780c37af3bSToby Isaac                   }
14790c37af3bSToby Isaac                   else {
14800c37af3bSToby Isaac                     insertCol = aSecOff + fComp * (parentOffsets[j + 1] - 1 - s);
14810c37af3bSToby Isaac                   }
14820c37af3bSToby Isaac                   for (t = 0; t < fComp; t++) {
14830c37af3bSToby Isaac                     ierr = MatSetValue(cMat,insertRow + t,insertCol + t,val,INSERT_VALUES);CHKERRQ(ierr);
14840c37af3bSToby Isaac                   }
14850c37af3bSToby Isaac                 }
14860c37af3bSToby Isaac               }
14870c37af3bSToby Isaac             }
14880c37af3bSToby Isaac           }
14890c37af3bSToby Isaac         }
14900c37af3bSToby Isaac       }
14910c37af3bSToby Isaac       ierr = PetscFree2(childOffsets,parentOffsets);CHKERRQ(ierr);
14920c37af3bSToby Isaac       ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
14930c37af3bSToby Isaac       ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSizeP,&closureP);CHKERRQ(ierr);
14940c37af3bSToby Isaac     }
14950c37af3bSToby Isaac     ierr = MatDestroy(&Amat);CHKERRQ(ierr);
14960c37af3bSToby Isaac     ierr = MatDestroy(&Bmat);CHKERRQ(ierr);
14970c37af3bSToby Isaac     ierr = MatDestroy(&Xmat);CHKERRQ(ierr);
14980c37af3bSToby Isaac     ierr = PetscFree3(weights,pointsRef,pointsReal);CHKERRQ(ierr);
14990c37af3bSToby Isaac   }
15000c37af3bSToby Isaac   ierr = MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15010c37af3bSToby Isaac   ierr = MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15020c37af3bSToby Isaac   ierr = PetscFree6(v0,v0parent,vtmp,J,Jparent,invJparent);CHKERRQ(ierr);
15030c37af3bSToby Isaac   ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);
15040c37af3bSToby Isaac 
15050c37af3bSToby Isaac   PetscFunctionReturn(0);
15060c37af3bSToby Isaac }
150795a0b26dSToby Isaac 
150895a0b26dSToby Isaac #undef __FUNCT__
1509f7c74593SToby Isaac #define __FUNCT__ "DMPlexComputeAnchorMatrix_Tree_FromReference"
1510f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm, PetscSection section, PetscSection conSec, Mat cMat)
151195a0b26dSToby Isaac {
151295a0b26dSToby Isaac   DM             refTree;
151395a0b26dSToby Isaac   PetscDS        ds;
1514f7c74593SToby Isaac   Mat            refCmat;
151595a0b26dSToby Isaac   PetscInt       numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof, maxAnDof, *perm, *iperm, pStart, pEnd, conStart, conEnd, **refPointFieldN;
151695a0b26dSToby Isaac   PetscScalar ***refPointFieldMats, *pointWork;
1517f7c74593SToby Isaac   PetscSection   refConSec, refAnSec, anSec, refSection;
151895a0b26dSToby Isaac   IS             refAnIS, anIS;
151995a0b26dSToby Isaac   const PetscInt *refAnchors, *anchors;
152095a0b26dSToby Isaac   PetscErrorCode ierr;
152195a0b26dSToby Isaac 
152295a0b26dSToby Isaac   PetscFunctionBegin;
152395a0b26dSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
152495a0b26dSToby Isaac   ierr = DMGetDS(dm,&ds);CHKERRQ(ierr);
152595a0b26dSToby Isaac   ierr = PetscDSGetNumFields(ds,&numFields);CHKERRQ(ierr);
152695a0b26dSToby Isaac   ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr);
152795a0b26dSToby Isaac   ierr = DMSetDS(refTree,ds);CHKERRQ(ierr);
1528f7c74593SToby Isaac   ierr = DMGetDefaultConstraints(refTree,&refConSec,&refCmat);CHKERRQ(ierr);
152995a0b26dSToby Isaac   ierr = DMPlexGetChart(refTree,&pRefStart,&pRefEnd);CHKERRQ(ierr);
1530a17985deSToby Isaac   ierr = DMPlexGetAnchors(refTree,&refAnSec,&refAnIS);CHKERRQ(ierr);
1531a17985deSToby Isaac   ierr = DMPlexGetAnchors(dm,&anSec,&anIS);CHKERRQ(ierr);
153295a0b26dSToby Isaac   ierr = ISGetIndices(refAnIS,&refAnchors);CHKERRQ(ierr);
153395a0b26dSToby Isaac   ierr = ISGetIndices(anIS,&anchors);CHKERRQ(ierr);
153495a0b26dSToby Isaac   ierr = DMGetDefaultSection(refTree,&refSection);CHKERRQ(ierr);
153595a0b26dSToby Isaac   ierr = PetscSectionGetChart(refConSec,&pRefStart,&pRefEnd);CHKERRQ(ierr);
153695a0b26dSToby Isaac   ierr = PetscSectionGetChart(conSec,&conStart,&conEnd);CHKERRQ(ierr);
153795a0b26dSToby Isaac   ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldMats);CHKERRQ(ierr);
153895a0b26dSToby Isaac   ierr = PetscMalloc1(pRefEnd-pRefStart,&refPointFieldN);CHKERRQ(ierr);
153995a0b26dSToby Isaac   ierr = PetscSectionGetMaxDof(refConSec,&maxDof);CHKERRQ(ierr);
154095a0b26dSToby Isaac   ierr = PetscSectionGetMaxDof(refAnSec,&maxAnDof);CHKERRQ(ierr);
154195a0b26dSToby Isaac   ierr = PetscMalloc1(maxDof,&rows);CHKERRQ(ierr);
154295a0b26dSToby Isaac   ierr = PetscMalloc1(maxDof*maxAnDof,&cols);CHKERRQ(ierr);
154395a0b26dSToby Isaac   ierr = PetscMalloc1(maxDof*maxDof*maxAnDof,&pointWork);CHKERRQ(ierr);
154495a0b26dSToby Isaac 
154595a0b26dSToby Isaac   /* step 1: get submats for every constrained point in the reference tree */
154695a0b26dSToby Isaac   for (p = pRefStart; p < pRefEnd; p++) {
154795a0b26dSToby Isaac     PetscInt parent, closureSize, *closure = NULL, pDof;
154895a0b26dSToby Isaac 
154995a0b26dSToby Isaac     ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr);
155095a0b26dSToby Isaac     ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr);
155195a0b26dSToby Isaac     if (!pDof || parent == p) continue;
155295a0b26dSToby Isaac 
155395a0b26dSToby Isaac     ierr = PetscMalloc1(numFields,&refPointFieldMats[p-pRefStart]);CHKERRQ(ierr);
155495a0b26dSToby Isaac     ierr = PetscCalloc1(numFields,&refPointFieldN[p-pRefStart]);CHKERRQ(ierr);
155595a0b26dSToby Isaac     ierr = DMPlexGetTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
155695a0b26dSToby Isaac     for (f = 0; f < numFields; f++) {
155795a0b26dSToby Isaac       PetscInt cDof, cOff, numCols, r, i, fComp;
15580dd1b1feSToby Isaac       PetscObject disc;
15590dd1b1feSToby Isaac       PetscClassId id;
15600dd1b1feSToby Isaac       PetscFE fe = NULL;
15610dd1b1feSToby Isaac       PetscFV fv = NULL;
156295a0b26dSToby Isaac 
15630dd1b1feSToby Isaac       ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr);
15640dd1b1feSToby Isaac       ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr);
15650dd1b1feSToby Isaac       if (id == PETSCFE_CLASSID) {
15660dd1b1feSToby Isaac         fe = (PetscFE) disc;
156795a0b26dSToby Isaac         ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr);
15680dd1b1feSToby Isaac       }
15690dd1b1feSToby Isaac       else if (id == PETSCFV_CLASSID) {
15700dd1b1feSToby Isaac         fv = (PetscFV) disc;
15710dd1b1feSToby Isaac         ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr);
15720dd1b1feSToby Isaac       }
15730dd1b1feSToby Isaac       else SETERRQ1(PetscObjectComm(disc),PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id);
157495a0b26dSToby Isaac 
157595a0b26dSToby Isaac       if (numFields > 1) {
157695a0b26dSToby Isaac         ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr);
157795a0b26dSToby Isaac         ierr = PetscSectionGetFieldOffset(refConSec,p,f,&cOff);CHKERRQ(ierr);
157895a0b26dSToby Isaac       }
157995a0b26dSToby Isaac       else {
158095a0b26dSToby Isaac         ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr);
158195a0b26dSToby Isaac         ierr = PetscSectionGetOffset(refConSec,p,&cOff);CHKERRQ(ierr);
158295a0b26dSToby Isaac       }
158395a0b26dSToby Isaac 
158495a0b26dSToby Isaac       if (!cDof) continue;
158595a0b26dSToby Isaac       for (r = 0; r < cDof; r++) {
158695a0b26dSToby Isaac         rows[r] = cOff + r;
158795a0b26dSToby Isaac       }
158895a0b26dSToby Isaac       numCols = 0;
158995a0b26dSToby Isaac       for (i = 0; i < closureSize; i++) {
159095a0b26dSToby Isaac         PetscInt q = closure[2*i];
159195a0b26dSToby Isaac         PetscInt o = closure[2*i+1];
159295a0b26dSToby Isaac         PetscInt aDof, aOff, j;
159395a0b26dSToby Isaac 
159495a0b26dSToby Isaac         if (numFields > 1) {
159595a0b26dSToby Isaac           ierr = PetscSectionGetFieldDof(refSection,q,f,&aDof);CHKERRQ(ierr);
159695a0b26dSToby Isaac           ierr = PetscSectionGetFieldOffset(refSection,q,f,&aOff);CHKERRQ(ierr);
159795a0b26dSToby Isaac         }
159895a0b26dSToby Isaac         else {
159995a0b26dSToby Isaac           ierr = PetscSectionGetDof(refSection,q,&aDof);CHKERRQ(ierr);
160095a0b26dSToby Isaac           ierr = PetscSectionGetOffset(refSection,q,&aOff);CHKERRQ(ierr);
160195a0b26dSToby Isaac         }
160295a0b26dSToby Isaac 
160395a0b26dSToby Isaac         for (j = 0; j < aDof; j++) {
160495a0b26dSToby Isaac           PetscInt node = (o >= 0) ? (j / fComp) : ((aDof - 1 - j) / fComp);
160595a0b26dSToby Isaac           PetscInt comp = (j % fComp);
160695a0b26dSToby Isaac 
160795a0b26dSToby Isaac           cols[numCols++] = aOff + node * fComp + comp;
160895a0b26dSToby Isaac         }
160995a0b26dSToby Isaac       }
161095a0b26dSToby Isaac       refPointFieldN[p-pRefStart][f] = numCols;
161195a0b26dSToby Isaac       ierr = PetscMalloc1(cDof*numCols,&refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr);
161295a0b26dSToby Isaac       ierr = MatGetValues(refCmat,cDof,rows,numCols,cols,refPointFieldMats[p-pRefStart][f]);CHKERRQ(ierr);
161395a0b26dSToby Isaac     }
161495a0b26dSToby Isaac     ierr = DMPlexRestoreTransitiveClosure(refTree,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
161595a0b26dSToby Isaac   }
161695a0b26dSToby Isaac 
161795a0b26dSToby Isaac   /* step 2: compute the preorder */
161895a0b26dSToby Isaac   ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr);
161995a0b26dSToby Isaac   ierr = PetscMalloc2(pEnd-pStart,&perm,pEnd-pStart,&iperm);CHKERRQ(ierr);
162095a0b26dSToby Isaac   for (p = pStart; p < pEnd; p++) {
162195a0b26dSToby Isaac     perm[p - pStart] = p;
162295a0b26dSToby Isaac     iperm[p - pStart] = p-pStart;
162395a0b26dSToby Isaac   }
162495a0b26dSToby Isaac   for (p = 0; p < pEnd - pStart;) {
162595a0b26dSToby Isaac     PetscInt point = perm[p];
162695a0b26dSToby Isaac     PetscInt parent;
162795a0b26dSToby Isaac 
162895a0b26dSToby Isaac     ierr = DMPlexGetTreeParent(dm,point,&parent,NULL);CHKERRQ(ierr);
162995a0b26dSToby Isaac     if (parent == point) {
163095a0b26dSToby Isaac       p++;
163195a0b26dSToby Isaac     }
163295a0b26dSToby Isaac     else {
163395a0b26dSToby Isaac       PetscInt size, closureSize, *closure = NULL, i;
163495a0b26dSToby Isaac 
163595a0b26dSToby Isaac       ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
163695a0b26dSToby Isaac       for (i = 0; i < closureSize; i++) {
163795a0b26dSToby Isaac         PetscInt q = closure[2*i];
163895a0b26dSToby Isaac         if (iperm[q-pStart] > iperm[point-pStart]) {
163995a0b26dSToby Isaac           /* swap */
164095a0b26dSToby Isaac           perm[p]               = q;
164195a0b26dSToby Isaac           perm[iperm[q-pStart]] = point;
164295a0b26dSToby Isaac           iperm[point-pStart]   = iperm[q-pStart];
164395a0b26dSToby Isaac           iperm[q-pStart]       = p;
164495a0b26dSToby Isaac           break;
164595a0b26dSToby Isaac         }
164695a0b26dSToby Isaac       }
164795a0b26dSToby Isaac       size = closureSize;
164895a0b26dSToby Isaac       ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
164995a0b26dSToby Isaac       if (i == size) {
165095a0b26dSToby Isaac         p++;
165195a0b26dSToby Isaac       }
165295a0b26dSToby Isaac     }
165395a0b26dSToby Isaac   }
165495a0b26dSToby Isaac 
165595a0b26dSToby Isaac   /* step 3: fill the constraint matrix */
165695a0b26dSToby Isaac   /* we are going to use a preorder progressive fill strategy.  Mat doesn't
165795a0b26dSToby Isaac    * allow progressive fill without assembly, so we are going to set up the
165895a0b26dSToby Isaac    * values outside of the Mat first.
165995a0b26dSToby Isaac    */
166095a0b26dSToby Isaac   {
166195a0b26dSToby Isaac     PetscInt nRows, row, nnz;
166295a0b26dSToby Isaac     PetscBool done;
166395a0b26dSToby Isaac     const PetscInt *ia, *ja;
166495a0b26dSToby Isaac     PetscScalar *vals;
166595a0b26dSToby Isaac 
166695a0b26dSToby Isaac     ierr = MatGetRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done);CHKERRQ(ierr);
166795a0b26dSToby Isaac     if (!done) SETERRQ(PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not get RowIJ of constraint matrix");
166895a0b26dSToby Isaac     nnz  = ia[nRows];
166995a0b26dSToby Isaac     /* malloc and then zero rows right before we fill them: this way valgrind
167095a0b26dSToby Isaac      * can tell if we are doing progressive fill in the wrong order */
167195a0b26dSToby Isaac     ierr = PetscMalloc1(nnz,&vals);CHKERRQ(ierr);
167295a0b26dSToby Isaac     for (p = 0; p < pEnd - pStart; p++) {
167395a0b26dSToby Isaac       PetscInt parent, childid, closureSize, *closure = NULL;
167495a0b26dSToby Isaac       PetscInt point = perm[p], pointDof;
167595a0b26dSToby Isaac 
167695a0b26dSToby Isaac       ierr = DMPlexGetTreeParent(dm,point,&parent,&childid);CHKERRQ(ierr);
167795a0b26dSToby Isaac       if ((point < conStart) || (point >= conEnd) || (parent == point)) continue;
167895a0b26dSToby Isaac       ierr = PetscSectionGetDof(conSec,point,&pointDof);CHKERRQ(ierr);
167995a0b26dSToby Isaac       if (!pointDof) continue;
168095a0b26dSToby Isaac       ierr = DMPlexGetTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
168195a0b26dSToby Isaac       for (f = 0; f < numFields; f++) {
168295a0b26dSToby Isaac         PetscInt cDof, cOff, numCols, numFillCols, i, r, fComp, matOffset, offset;
168395a0b26dSToby Isaac         PetscScalar *pointMat;
16840dd1b1feSToby Isaac         PetscObject disc;
16850dd1b1feSToby Isaac         PetscClassId id;
16860dd1b1feSToby Isaac         PetscFE fe = NULL;
16870dd1b1feSToby Isaac         PetscFV fv = NULL;
168895a0b26dSToby Isaac 
16890dd1b1feSToby Isaac         ierr = PetscDSGetDiscretization(ds,f,&disc);CHKERRQ(ierr);
16900dd1b1feSToby Isaac         ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr);
16910dd1b1feSToby Isaac         if (id == PETSCFE_CLASSID) {
16920dd1b1feSToby Isaac           fe = (PetscFE) disc;
169395a0b26dSToby Isaac           ierr = PetscFEGetNumComponents(fe,&fComp);CHKERRQ(ierr);
16940dd1b1feSToby Isaac         }
16950dd1b1feSToby Isaac         else if (id == PETSCFV_CLASSID) {
16960dd1b1feSToby Isaac           fv = (PetscFV) disc;
16970dd1b1feSToby Isaac           ierr = PetscFVGetNumComponents(fv,&fComp);CHKERRQ(ierr);
16980dd1b1feSToby Isaac         }
169995a0b26dSToby Isaac 
170095a0b26dSToby Isaac         if (numFields > 1) {
170195a0b26dSToby Isaac           ierr = PetscSectionGetFieldDof(conSec,point,f,&cDof);CHKERRQ(ierr);
170295a0b26dSToby Isaac           ierr = PetscSectionGetFieldOffset(conSec,point,f,&cOff);CHKERRQ(ierr);
170395a0b26dSToby Isaac         }
170495a0b26dSToby Isaac         else {
170595a0b26dSToby Isaac           ierr = PetscSectionGetDof(conSec,point,&cDof);CHKERRQ(ierr);
170695a0b26dSToby Isaac           ierr = PetscSectionGetOffset(conSec,point,&cOff);CHKERRQ(ierr);
170795a0b26dSToby Isaac         }
170895a0b26dSToby Isaac         if (!cDof) continue;
170995a0b26dSToby Isaac 
171095a0b26dSToby Isaac         /* make sure that every row for this point is the same size */
171195a0b26dSToby Isaac #if defined(PETSC_USE_DEBUG)
171295a0b26dSToby Isaac         for (r = 0; r < cDof; r++) {
171395a0b26dSToby Isaac           if (cDof > 1 && r) {
17146c4ed002SBarry Smith             if ((ia[cOff+r+1]-ia[cOff+r]) != (ia[cOff+r]-ia[cOff+r-1])) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Two point rows have different nnz: %D vs. %D", (ia[rows[r]+1]-ia[rows[r]]), (ia[rows[r]]-ia[rows[r]-1]));
171595a0b26dSToby Isaac           }
171695a0b26dSToby Isaac         }
171795a0b26dSToby Isaac #endif
171895a0b26dSToby Isaac         /* zero rows */
171995a0b26dSToby Isaac         for (i = ia[cOff] ; i< ia[cOff+cDof];i++) {
172095a0b26dSToby Isaac           vals[i] = 0.;
172195a0b26dSToby Isaac         }
172295a0b26dSToby Isaac         matOffset = ia[cOff];
172395a0b26dSToby Isaac         numFillCols = ia[cOff+1] - matOffset;
172495a0b26dSToby Isaac         pointMat = refPointFieldMats[childid-pRefStart][f];
172595a0b26dSToby Isaac         numCols = refPointFieldN[childid-pRefStart][f];
172695a0b26dSToby Isaac         offset = 0;
172795a0b26dSToby Isaac         for (i = 0; i < closureSize; i++) {
172895a0b26dSToby Isaac           PetscInt q = closure[2*i];
172995a0b26dSToby Isaac           PetscInt o = closure[2*i+1];
173095a0b26dSToby Isaac           PetscInt aDof, aOff, j, k, qConDof, qConOff;
173195a0b26dSToby Isaac 
173295a0b26dSToby Isaac           qConDof = qConOff = 0;
173395a0b26dSToby Isaac           if (numFields > 1) {
173495a0b26dSToby Isaac             ierr = PetscSectionGetFieldDof(section,q,f,&aDof);CHKERRQ(ierr);
173595a0b26dSToby Isaac             ierr = PetscSectionGetFieldOffset(section,q,f,&aOff);CHKERRQ(ierr);
173695a0b26dSToby Isaac             if (q >= conStart && q < conEnd) {
173795a0b26dSToby Isaac               ierr = PetscSectionGetFieldDof(conSec,q,f,&qConDof);CHKERRQ(ierr);
173895a0b26dSToby Isaac               ierr = PetscSectionGetFieldOffset(conSec,q,f,&qConOff);CHKERRQ(ierr);
173995a0b26dSToby Isaac             }
174095a0b26dSToby Isaac           }
174195a0b26dSToby Isaac           else {
174295a0b26dSToby Isaac             ierr = PetscSectionGetDof(section,q,&aDof);CHKERRQ(ierr);
174395a0b26dSToby Isaac             ierr = PetscSectionGetOffset(section,q,&aOff);CHKERRQ(ierr);
174495a0b26dSToby Isaac             if (q >= conStart && q < conEnd) {
174595a0b26dSToby Isaac               ierr = PetscSectionGetDof(conSec,q,&qConDof);CHKERRQ(ierr);
174695a0b26dSToby Isaac               ierr = PetscSectionGetOffset(conSec,q,&qConOff);CHKERRQ(ierr);
174795a0b26dSToby Isaac             }
174895a0b26dSToby Isaac           }
174995a0b26dSToby Isaac           if (!aDof) continue;
175095a0b26dSToby Isaac           if (qConDof) {
175195a0b26dSToby Isaac             /* this point has anchors: its rows of the matrix should already
175295a0b26dSToby Isaac              * be filled, thanks to preordering */
175395a0b26dSToby Isaac             /* first multiply into pointWork, then set in matrix */
175495a0b26dSToby Isaac             PetscInt aMatOffset = ia[qConOff];
175595a0b26dSToby Isaac             PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset;
175695a0b26dSToby Isaac             for (r = 0; r < cDof; r++) {
175795a0b26dSToby Isaac               for (j = 0; j < aNumFillCols; j++) {
175895a0b26dSToby Isaac                 PetscScalar inVal = 0;
175995a0b26dSToby Isaac                 for (k = 0; k < aDof; k++) {
176095a0b26dSToby Isaac                   PetscInt node = (o >= 0) ? (k / fComp) : ((aDof - 1 - k) / fComp);
176195a0b26dSToby Isaac                   PetscInt comp = (k % fComp);
176295a0b26dSToby Isaac                   PetscInt col  = node * fComp + comp;
176395a0b26dSToby Isaac 
176495a0b26dSToby Isaac                   inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j];
176595a0b26dSToby Isaac                 }
176695a0b26dSToby Isaac                 pointWork[r * aNumFillCols + j] = inVal;
176795a0b26dSToby Isaac               }
176895a0b26dSToby Isaac             }
176995a0b26dSToby Isaac             /* assume that the columns are sorted, spend less time searching */
177095a0b26dSToby Isaac             for (j = 0, k = 0; j < aNumFillCols; j++) {
177195a0b26dSToby Isaac               PetscInt col = ja[aMatOffset + j];
177295a0b26dSToby Isaac               for (;k < numFillCols; k++) {
177395a0b26dSToby Isaac                 if (ja[matOffset + k] == col) {
177495a0b26dSToby Isaac                   break;
177595a0b26dSToby Isaac                 }
177695a0b26dSToby Isaac               }
177795a0b26dSToby Isaac               if (k == numFillCols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, col);
177895a0b26dSToby Isaac               for (r = 0; r < cDof; r++) {
177995a0b26dSToby Isaac                 vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j];
178095a0b26dSToby Isaac               }
178195a0b26dSToby Isaac             }
178295a0b26dSToby Isaac           }
178395a0b26dSToby Isaac           else {
178495a0b26dSToby Isaac             /* find where to put this portion of pointMat into the matrix */
178595a0b26dSToby Isaac             for (k = 0; k < numFillCols; k++) {
178695a0b26dSToby Isaac               if (ja[matOffset + k] == aOff) {
178795a0b26dSToby Isaac                 break;
178895a0b26dSToby Isaac               }
178995a0b26dSToby Isaac             }
179095a0b26dSToby Isaac             if (k == numFillCols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"No nonzero space for (%d, %d)", cOff, aOff);
179195a0b26dSToby Isaac             for (j = 0; j < aDof; j++) {
179295a0b26dSToby Isaac               PetscInt node = (o >= 0) ? (j / fComp) : ((aDof - 1 - j) / fComp);
179395a0b26dSToby Isaac               PetscInt comp = (j % fComp);
179495a0b26dSToby Isaac               PetscInt col  = node * fComp + comp;
179595a0b26dSToby Isaac               for (r = 0; r < cDof; r++) {
179695a0b26dSToby Isaac                 vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + col];
179795a0b26dSToby Isaac               }
179895a0b26dSToby Isaac             }
179995a0b26dSToby Isaac           }
180095a0b26dSToby Isaac           offset += aDof;
180195a0b26dSToby Isaac         }
180295a0b26dSToby Isaac       }
180395a0b26dSToby Isaac       ierr = DMPlexRestoreTransitiveClosure(dm,parent,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
180495a0b26dSToby Isaac     }
180595a0b26dSToby Isaac     for (row = 0; row < nRows; row++) {
180695a0b26dSToby Isaac       ierr = MatSetValues(cMat,1,&row,ia[row+1]-ia[row],&ja[ia[row]],&vals[ia[row]],INSERT_VALUES);CHKERRQ(ierr);
180795a0b26dSToby Isaac     }
180895a0b26dSToby Isaac     ierr = MatRestoreRowIJ(cMat,0,PETSC_FALSE,PETSC_FALSE,&nRows,&ia,&ja,&done);CHKERRQ(ierr);
180995a0b26dSToby Isaac     if (!done) SETERRQ(PetscObjectComm((PetscObject)cMat),PETSC_ERR_PLIB,"Could not restore RowIJ of constraint matrix");
181095a0b26dSToby Isaac     ierr = MatAssemblyBegin(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
181195a0b26dSToby Isaac     ierr = MatAssemblyEnd(cMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
181295a0b26dSToby Isaac     ierr = PetscFree(vals);CHKERRQ(ierr);
181395a0b26dSToby Isaac   }
181495a0b26dSToby Isaac 
181595a0b26dSToby Isaac   /* clean up */
181695a0b26dSToby Isaac   ierr = ISRestoreIndices(refAnIS,&refAnchors);CHKERRQ(ierr);
181795a0b26dSToby Isaac   ierr = ISRestoreIndices(anIS,&anchors);CHKERRQ(ierr);
181895a0b26dSToby Isaac   ierr = PetscFree2(perm,iperm);CHKERRQ(ierr);
181995a0b26dSToby Isaac   ierr = PetscFree(rows);CHKERRQ(ierr);
182095a0b26dSToby Isaac   ierr = PetscFree(cols);CHKERRQ(ierr);
182195a0b26dSToby Isaac   ierr = PetscFree(pointWork);CHKERRQ(ierr);
182295a0b26dSToby Isaac   for (p = pRefStart; p < pRefEnd; p++) {
182395a0b26dSToby Isaac     PetscInt parent, pDof;
182495a0b26dSToby Isaac 
182595a0b26dSToby Isaac     ierr = DMPlexGetTreeParent(refTree,p,&parent,NULL);CHKERRQ(ierr);
182695a0b26dSToby Isaac     ierr = PetscSectionGetDof(refConSec,p,&pDof);CHKERRQ(ierr);
182795a0b26dSToby Isaac     if (!pDof || parent == p) continue;
182895a0b26dSToby Isaac 
182995a0b26dSToby Isaac     for (f = 0; f < numFields; f++) {
183095a0b26dSToby Isaac       PetscInt cDof;
183195a0b26dSToby Isaac 
183295a0b26dSToby Isaac       if (numFields > 1) {
183395a0b26dSToby Isaac         ierr = PetscSectionGetFieldDof(refConSec,p,f,&cDof);CHKERRQ(ierr);
183495a0b26dSToby Isaac       }
183595a0b26dSToby Isaac       else {
183695a0b26dSToby Isaac         ierr = PetscSectionGetDof(refConSec,p,&cDof);CHKERRQ(ierr);
183795a0b26dSToby Isaac       }
183895a0b26dSToby Isaac 
183995a0b26dSToby Isaac       if (!cDof) continue;
184095a0b26dSToby Isaac       ierr = PetscFree(refPointFieldMats[p - pRefStart][f]);CHKERRQ(ierr);
184195a0b26dSToby Isaac     }
184295a0b26dSToby Isaac     ierr = PetscFree(refPointFieldMats[p - pRefStart]);CHKERRQ(ierr);
184395a0b26dSToby Isaac     ierr = PetscFree(refPointFieldN[p - pRefStart]);CHKERRQ(ierr);
184495a0b26dSToby Isaac   }
184595a0b26dSToby Isaac   ierr = PetscFree(refPointFieldMats);CHKERRQ(ierr);
184695a0b26dSToby Isaac   ierr = PetscFree(refPointFieldN);CHKERRQ(ierr);
184795a0b26dSToby Isaac   PetscFunctionReturn(0);
184895a0b26dSToby Isaac }
184995a0b26dSToby Isaac 
18506f5f1567SToby Isaac #undef __FUNCT__
18516f5f1567SToby Isaac #define __FUNCT__ "DMPlexTreeRefineCell"
18526f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of
18536f5f1567SToby Isaac  * a non-conforming mesh.  Local refinement comes later */
18546f5f1567SToby Isaac PetscErrorCode DMPlexTreeRefineCell (DM dm, PetscInt cell, DM *ncdm)
18556f5f1567SToby Isaac {
18566f5f1567SToby Isaac   DM K;
1857420f55faSMatthew G. Knepley   PetscMPIInt rank;
18586f5f1567SToby Isaac   PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd;
18596f5f1567SToby Isaac   PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations;
18606f5f1567SToby Isaac   PetscInt *Kembedding;
18616f5f1567SToby Isaac   PetscInt *cellClosure=NULL, nc;
18626f5f1567SToby Isaac   PetscScalar *newVertexCoords;
18636f5f1567SToby Isaac   PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset;
18646f5f1567SToby Isaac   PetscSection parentSection;
18656f5f1567SToby Isaac   PetscErrorCode ierr;
18666f5f1567SToby Isaac 
18676f5f1567SToby Isaac   PetscFunctionBegin;
18686f5f1567SToby Isaac   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
186928f4b327SMatthew G. Knepley   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
18706f5f1567SToby Isaac   ierr = DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm);CHKERRQ(ierr);
187128f4b327SMatthew G. Knepley   ierr = DMSetDimension(*ncdm,dim);CHKERRQ(ierr);
18726f5f1567SToby Isaac 
18736f5f1567SToby Isaac   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
18746f5f1567SToby Isaac   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&parentSection);CHKERRQ(ierr);
18756f5f1567SToby Isaac   ierr = DMPlexGetReferenceTree(dm,&K);CHKERRQ(ierr);
18766f5f1567SToby Isaac   if (!rank) {
18776f5f1567SToby Isaac     /* compute the new charts */
18786f5f1567SToby Isaac     ierr = PetscMalloc5(dim+1,&pNewCount,dim+1,&pNewStart,dim+1,&pNewEnd,dim+1,&pOldStart,dim+1,&pOldEnd);CHKERRQ(ierr);
18796f5f1567SToby Isaac     offset = 0;
18806f5f1567SToby Isaac     for (d = 0; d <= dim; d++) {
18816f5f1567SToby Isaac       PetscInt pOldCount, kStart, kEnd, k;
18826f5f1567SToby Isaac 
18836f5f1567SToby Isaac       pNewStart[d] = offset;
18846f5f1567SToby Isaac       ierr = DMPlexGetHeightStratum(dm,d,&pOldStart[d],&pOldEnd[d]);CHKERRQ(ierr);
18856f5f1567SToby Isaac       ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr);
18866f5f1567SToby Isaac       pOldCount = pOldEnd[d] - pOldStart[d];
18876f5f1567SToby Isaac       /* adding the new points */
18886f5f1567SToby Isaac       pNewCount[d] = pOldCount + kEnd - kStart;
18896f5f1567SToby Isaac       if (!d) {
18906f5f1567SToby Isaac         /* removing the cell */
18916f5f1567SToby Isaac         pNewCount[d]--;
18926f5f1567SToby Isaac       }
18936f5f1567SToby Isaac       for (k = kStart; k < kEnd; k++) {
18946f5f1567SToby Isaac         PetscInt parent;
18956f5f1567SToby Isaac         ierr = DMPlexGetTreeParent(K,k,&parent,NULL);CHKERRQ(ierr);
18966f5f1567SToby Isaac         if (parent == k) {
18976f5f1567SToby Isaac           /* avoid double counting points that won't actually be new */
18986f5f1567SToby Isaac           pNewCount[d]--;
18996f5f1567SToby Isaac         }
19006f5f1567SToby Isaac       }
19016f5f1567SToby Isaac       pNewEnd[d] = pNewStart[d] + pNewCount[d];
19026f5f1567SToby Isaac       offset = pNewEnd[d];
19036f5f1567SToby Isaac 
19046f5f1567SToby Isaac     }
19056f5f1567SToby Isaac     if (cell < pOldStart[0] || cell >= pOldEnd[0]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"%d not in cell range [%d, %d)", cell, pOldStart[0], pOldEnd[0]);
19066f5f1567SToby Isaac     /* get the current closure of the cell that we are removing */
19076f5f1567SToby Isaac     ierr = DMPlexGetTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure);CHKERRQ(ierr);
19086f5f1567SToby Isaac 
19096f5f1567SToby Isaac     ierr = PetscMalloc1(pNewEnd[dim],&newConeSizes);CHKERRQ(ierr);
19106f5f1567SToby Isaac     {
19116f5f1567SToby Isaac       PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j;
19126f5f1567SToby Isaac 
19136f5f1567SToby Isaac       ierr = DMPlexGetChart(K,&kStart,&kEnd);CHKERRQ(ierr);
19146f5f1567SToby Isaac       ierr = PetscMalloc4(kEnd-kStart,&Kembedding,kEnd-kStart,&perm,kEnd-kStart,&iperm,kEnd-kStart,&preOrient);CHKERRQ(ierr);
19156f5f1567SToby Isaac 
19166f5f1567SToby Isaac       for (k = kStart; k < kEnd; k++) {
19176f5f1567SToby Isaac         perm[k - kStart] = k;
19186f5f1567SToby Isaac         iperm [k - kStart] = k - kStart;
19196f5f1567SToby Isaac         preOrient[k - kStart] = 0;
19206f5f1567SToby Isaac       }
19216f5f1567SToby Isaac 
19226f5f1567SToby Isaac       ierr = DMPlexGetTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK);CHKERRQ(ierr);
19236f5f1567SToby Isaac       for (j = 1; j < closureSizeK; j++) {
19246f5f1567SToby Isaac         PetscInt parentOrientA = closureK[2*j+1];
19256f5f1567SToby Isaac         PetscInt parentOrientB = cellClosure[2*j+1];
19266f5f1567SToby Isaac         PetscInt p, q;
19276f5f1567SToby Isaac 
19286f5f1567SToby Isaac         p = closureK[2*j];
19296f5f1567SToby Isaac         q = cellClosure[2*j];
19306f5f1567SToby Isaac         for (d = 0; d <= dim; d++) {
19316f5f1567SToby Isaac           if (q >= pOldStart[d] && q < pOldEnd[d]) {
19326f5f1567SToby Isaac             Kembedding[p] = (q - pOldStart[d]) + pNewStart[d];
19336f5f1567SToby Isaac           }
19346f5f1567SToby Isaac         }
19356f5f1567SToby Isaac         if (parentOrientA != parentOrientB) {
19366f5f1567SToby Isaac           PetscInt numChildren, i;
19376f5f1567SToby Isaac           const PetscInt *children;
19386f5f1567SToby Isaac 
19396f5f1567SToby Isaac           ierr = DMPlexGetTreeChildren(K,p,&numChildren,&children);CHKERRQ(ierr);
19406f5f1567SToby Isaac           for (i = 0; i < numChildren; i++) {
19416f5f1567SToby Isaac             PetscInt kPerm, oPerm;
19426f5f1567SToby Isaac 
19436f5f1567SToby Isaac             k    = children[i];
19446f5f1567SToby Isaac             ierr = DMPlexReferenceTreeGetChildSymmetry(K,p,parentOrientA,0,k,parentOrientB,&oPerm,&kPerm);CHKERRQ(ierr);
19456f5f1567SToby Isaac             /* perm = what refTree position I'm in */
19466f5f1567SToby Isaac             perm[kPerm-kStart]      = k;
19476f5f1567SToby Isaac             /* iperm = who is at this position */
19486f5f1567SToby Isaac             iperm[k-kStart]         = kPerm-kStart;
19496f5f1567SToby Isaac             preOrient[kPerm-kStart] = oPerm;
19506f5f1567SToby Isaac           }
19516f5f1567SToby Isaac         }
19526f5f1567SToby Isaac       }
19536f5f1567SToby Isaac       ierr = DMPlexRestoreTransitiveClosure(K,0,PETSC_TRUE,&closureSizeK,&closureK);CHKERRQ(ierr);
19546f5f1567SToby Isaac     }
19556f5f1567SToby Isaac     ierr = PetscSectionSetChart(parentSection,0,pNewEnd[dim]);CHKERRQ(ierr);
19566f5f1567SToby Isaac     offset = 0;
19576f5f1567SToby Isaac     numNewCones = 0;
19586f5f1567SToby Isaac     for (d = 0; d <= dim; d++) {
19596f5f1567SToby Isaac       PetscInt kStart, kEnd, k;
19606f5f1567SToby Isaac       PetscInt p;
19616f5f1567SToby Isaac       PetscInt size;
19626f5f1567SToby Isaac 
19636f5f1567SToby Isaac       for (p = pOldStart[d]; p < pOldEnd[d]; p++) {
19646f5f1567SToby Isaac         /* skip cell 0 */
19656f5f1567SToby Isaac         if (p == cell) continue;
19666f5f1567SToby Isaac         /* old cones to new cones */
19676f5f1567SToby Isaac         ierr = DMPlexGetConeSize(dm,p,&size);CHKERRQ(ierr);
19686f5f1567SToby Isaac         newConeSizes[offset++] = size;
19696f5f1567SToby Isaac         numNewCones += size;
19706f5f1567SToby Isaac       }
19716f5f1567SToby Isaac 
19726f5f1567SToby Isaac       ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr);
19736f5f1567SToby Isaac       for (k = kStart; k < kEnd; k++) {
19746f5f1567SToby Isaac         PetscInt kParent;
19756f5f1567SToby Isaac 
19766f5f1567SToby Isaac         ierr = DMPlexGetTreeParent(K,k,&kParent,NULL);CHKERRQ(ierr);
19776f5f1567SToby Isaac         if (kParent != k) {
19786f5f1567SToby Isaac           Kembedding[k] = offset;
19796f5f1567SToby Isaac           ierr = DMPlexGetConeSize(K,k,&size);CHKERRQ(ierr);
19806f5f1567SToby Isaac           newConeSizes[offset++] = size;
19816f5f1567SToby Isaac           numNewCones += size;
19826f5f1567SToby Isaac           if (kParent != 0) {
19836f5f1567SToby Isaac             ierr = PetscSectionSetDof(parentSection,Kembedding[k],1);CHKERRQ(ierr);
19846f5f1567SToby Isaac           }
19856f5f1567SToby Isaac         }
19866f5f1567SToby Isaac       }
19876f5f1567SToby Isaac     }
19886f5f1567SToby Isaac 
19896f5f1567SToby Isaac     ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr);
19906f5f1567SToby Isaac     ierr = PetscSectionGetStorageSize(parentSection,&numPointsWithParents);CHKERRQ(ierr);
19916f5f1567SToby Isaac     ierr = PetscMalloc2(numNewCones,&newCones,numNewCones,&newOrientations);CHKERRQ(ierr);
19926f5f1567SToby Isaac     ierr = PetscMalloc2(numPointsWithParents,&parents,numPointsWithParents,&childIDs);CHKERRQ(ierr);
19936f5f1567SToby Isaac 
19946f5f1567SToby Isaac     /* fill new cones */
19956f5f1567SToby Isaac     offset = 0;
19966f5f1567SToby Isaac     for (d = 0; d <= dim; d++) {
19976f5f1567SToby Isaac       PetscInt kStart, kEnd, k, l;
19986f5f1567SToby Isaac       PetscInt p;
19996f5f1567SToby Isaac       PetscInt size;
20006f5f1567SToby Isaac       const PetscInt *cone, *orientation;
20016f5f1567SToby Isaac 
20026f5f1567SToby Isaac       for (p = pOldStart[d]; p < pOldEnd[d]; p++) {
20036f5f1567SToby Isaac         /* skip cell 0 */
20046f5f1567SToby Isaac         if (p == cell) continue;
20056f5f1567SToby Isaac         /* old cones to new cones */
20066f5f1567SToby Isaac         ierr = DMPlexGetConeSize(dm,p,&size);CHKERRQ(ierr);
20076f5f1567SToby Isaac         ierr = DMPlexGetCone(dm,p,&cone);CHKERRQ(ierr);
20086f5f1567SToby Isaac         ierr = DMPlexGetConeOrientation(dm,p,&orientation);CHKERRQ(ierr);
20096f5f1567SToby Isaac         for (l = 0; l < size; l++) {
20106f5f1567SToby Isaac           newCones[offset]          = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1];
20116f5f1567SToby Isaac           newOrientations[offset++] = orientation[l];
20126f5f1567SToby Isaac         }
20136f5f1567SToby Isaac       }
20146f5f1567SToby Isaac 
20156f5f1567SToby Isaac       ierr = DMPlexGetHeightStratum(K,d,&kStart,&kEnd);CHKERRQ(ierr);
20166f5f1567SToby Isaac       for (k = kStart; k < kEnd; k++) {
20176f5f1567SToby Isaac         PetscInt kPerm = perm[k], kParent;
20186f5f1567SToby Isaac         PetscInt preO  = preOrient[k];
20196f5f1567SToby Isaac 
20206f5f1567SToby Isaac         ierr = DMPlexGetTreeParent(K,k,&kParent,NULL);CHKERRQ(ierr);
20216f5f1567SToby Isaac         if (kParent != k) {
20226f5f1567SToby Isaac           /* embed new cones */
20236f5f1567SToby Isaac           ierr = DMPlexGetConeSize(K,k,&size);CHKERRQ(ierr);
20246f5f1567SToby Isaac           ierr = DMPlexGetCone(K,kPerm,&cone);CHKERRQ(ierr);
20256f5f1567SToby Isaac           ierr = DMPlexGetConeOrientation(K,kPerm,&orientation);CHKERRQ(ierr);
20266f5f1567SToby Isaac           for (l = 0; l < size; l++) {
20276f5f1567SToby Isaac             PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size -(preO + 1) - l) % size);
20286f5f1567SToby Isaac             PetscInt newO, lSize, oTrue;
20296f5f1567SToby Isaac 
20306f5f1567SToby Isaac             q                         = iperm[cone[m]];
20316f5f1567SToby Isaac             newCones[offset]          = Kembedding[q];
20326f5f1567SToby Isaac             ierr                      = DMPlexGetConeSize(K,q,&lSize);CHKERRQ(ierr);
20336f5f1567SToby Isaac             oTrue                     = orientation[m];
20346f5f1567SToby Isaac             oTrue                     = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2);
20356f5f1567SToby Isaac             newO                      = DihedralCompose(lSize,oTrue,preOrient[q]);
20366f5f1567SToby Isaac             newOrientations[offset++] = newO;
20376f5f1567SToby Isaac           }
20386f5f1567SToby Isaac           if (kParent != 0) {
20396f5f1567SToby Isaac             PetscInt newPoint = Kembedding[kParent];
20406f5f1567SToby Isaac             ierr              = PetscSectionGetOffset(parentSection,Kembedding[k],&pOffset);CHKERRQ(ierr);
20416f5f1567SToby Isaac             parents[pOffset]  = newPoint;
20426f5f1567SToby Isaac             childIDs[pOffset] = k;
20436f5f1567SToby Isaac           }
20446f5f1567SToby Isaac         }
20456f5f1567SToby Isaac       }
20466f5f1567SToby Isaac     }
20476f5f1567SToby Isaac 
20486f5f1567SToby Isaac     ierr = PetscMalloc1(dim*(pNewEnd[dim]-pNewStart[dim]),&newVertexCoords);CHKERRQ(ierr);
20496f5f1567SToby Isaac 
20506f5f1567SToby Isaac     /* fill coordinates */
20516f5f1567SToby Isaac     offset = 0;
20526f5f1567SToby Isaac     {
2053d90620a3SMatthew G. Knepley       PetscInt kStart, kEnd, l;
20546f5f1567SToby Isaac       PetscSection vSection;
20556f5f1567SToby Isaac       PetscInt v;
20566f5f1567SToby Isaac       Vec coords;
20576f5f1567SToby Isaac       PetscScalar *coordvals;
20586f5f1567SToby Isaac       PetscInt dof, off;
2059c111c6b7SMatthew G. Knepley       PetscReal v0[3], J[9], detJ;
20606f5f1567SToby Isaac 
20616f5f1567SToby Isaac #if defined(PETSC_USE_DEBUG)
2062d90620a3SMatthew G. Knepley       {
2063d90620a3SMatthew G. Knepley         PetscInt k;
20646f5f1567SToby Isaac         ierr = DMPlexGetHeightStratum(K,0,&kStart,&kEnd);CHKERRQ(ierr);
20656f5f1567SToby Isaac         for (k = kStart; k < kEnd; k++) {
206673a7f2aaSMatthew G. Knepley           ierr = DMPlexComputeCellGeometryFEM(K, k, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr);
20676f5f1567SToby Isaac           if (detJ <= 0.) SETERRQ1 (PETSC_COMM_SELF,PETSC_ERR_PLIB,"reference tree cell %d has bad determinant",k);
20686f5f1567SToby Isaac         }
2069d90620a3SMatthew G. Knepley       }
20706f5f1567SToby Isaac #endif
207173a7f2aaSMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr);
20726f5f1567SToby Isaac       ierr = DMGetCoordinateSection(dm,&vSection);CHKERRQ(ierr);
20736f5f1567SToby Isaac       ierr = DMGetCoordinatesLocal(dm,&coords);CHKERRQ(ierr);
20746f5f1567SToby Isaac       ierr = VecGetArray(coords,&coordvals);CHKERRQ(ierr);
20756f5f1567SToby Isaac       for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) {
20766f5f1567SToby Isaac 
20776f5f1567SToby Isaac         ierr = PetscSectionGetDof(vSection,v,&dof);CHKERRQ(ierr);
20786f5f1567SToby Isaac         ierr = PetscSectionGetOffset(vSection,v,&off);CHKERRQ(ierr);
20796f5f1567SToby Isaac         for (l = 0; l < dof; l++) {
20806f5f1567SToby Isaac           newVertexCoords[offset++] = coordvals[off + l];
20816f5f1567SToby Isaac         }
20826f5f1567SToby Isaac       }
20836f5f1567SToby Isaac       ierr = VecRestoreArray(coords,&coordvals);CHKERRQ(ierr);
20846f5f1567SToby Isaac 
20856f5f1567SToby Isaac       ierr = DMGetCoordinateSection(K,&vSection);CHKERRQ(ierr);
20866f5f1567SToby Isaac       ierr = DMGetCoordinatesLocal(K,&coords);CHKERRQ(ierr);
20876f5f1567SToby Isaac       ierr = VecGetArray(coords,&coordvals);CHKERRQ(ierr);
20886f5f1567SToby Isaac       ierr = DMPlexGetDepthStratum(K,0,&kStart,&kEnd);CHKERRQ(ierr);
20896f5f1567SToby Isaac       for (v = kStart; v < kEnd; v++) {
20909bc368c7SMatthew G. Knepley         PetscReal coord[3], newCoord[3];
20916f5f1567SToby Isaac         PetscInt  vPerm = perm[v];
20926f5f1567SToby Isaac         PetscInt  kParent;
20936f5f1567SToby Isaac 
20946f5f1567SToby Isaac         ierr = DMPlexGetTreeParent(K,v,&kParent,NULL);CHKERRQ(ierr);
20956f5f1567SToby Isaac         if (kParent != v) {
20966f5f1567SToby Isaac           /* this is a new vertex */
20976f5f1567SToby Isaac           ierr = PetscSectionGetOffset(vSection,vPerm,&off);CHKERRQ(ierr);
20989bc368c7SMatthew G. Knepley           for (l = 0; l < dim; ++l) coord[l] = PetscRealPart(coordvals[off+l]);
20999bc368c7SMatthew G. Knepley           CoordinatesRefToReal(dim, dim, v0, J, coord, newCoord);CHKERRQ(ierr);
21009bc368c7SMatthew G. Knepley           for (l = 0; l < dim; ++l) newVertexCoords[offset+l] = newCoord[l];
21016f5f1567SToby Isaac           offset += dim;
21026f5f1567SToby Isaac         }
21036f5f1567SToby Isaac       }
21046f5f1567SToby Isaac       ierr = VecRestoreArray(coords,&coordvals);CHKERRQ(ierr);
21056f5f1567SToby Isaac     }
21066f5f1567SToby Isaac 
21076f5f1567SToby Isaac     /* need to reverse the order of pNewCount: vertices first, cells last */
21086f5f1567SToby Isaac     for (d = 0; d < (dim + 1) / 2; d++) {
21096f5f1567SToby Isaac       PetscInt tmp;
21106f5f1567SToby Isaac 
21116f5f1567SToby Isaac       tmp = pNewCount[d];
21126f5f1567SToby Isaac       pNewCount[d] = pNewCount[dim - d];
21136f5f1567SToby Isaac       pNewCount[dim - d] = tmp;
21146f5f1567SToby Isaac     }
21156f5f1567SToby Isaac 
21166f5f1567SToby Isaac     ierr = DMPlexCreateFromDAG(*ncdm,dim,pNewCount,newConeSizes,newCones,newOrientations,newVertexCoords);CHKERRQ(ierr);
21176f5f1567SToby Isaac     ierr = DMPlexSetReferenceTree(*ncdm,K);CHKERRQ(ierr);
21186f5f1567SToby Isaac     ierr = DMPlexSetTree(*ncdm,parentSection,parents,childIDs);CHKERRQ(ierr);
21196f5f1567SToby Isaac 
21206f5f1567SToby Isaac     /* clean up */
21216f5f1567SToby Isaac     ierr = DMPlexRestoreTransitiveClosure(dm,cell,PETSC_TRUE,&nc,&cellClosure);CHKERRQ(ierr);
21226f5f1567SToby Isaac     ierr = PetscFree5(pNewCount,pNewStart,pNewEnd,pOldStart,pOldEnd);CHKERRQ(ierr);
21236f5f1567SToby Isaac     ierr = PetscFree(newConeSizes);CHKERRQ(ierr);
21246f5f1567SToby Isaac     ierr = PetscFree2(newCones,newOrientations);CHKERRQ(ierr);
21256f5f1567SToby Isaac     ierr = PetscFree(newVertexCoords);CHKERRQ(ierr);
21266f5f1567SToby Isaac     ierr = PetscFree2(parents,childIDs);CHKERRQ(ierr);
21276f5f1567SToby Isaac     ierr = PetscFree4(Kembedding,perm,iperm,preOrient);CHKERRQ(ierr);
21286f5f1567SToby Isaac   }
21296f5f1567SToby Isaac   else {
21306f5f1567SToby Isaac     PetscInt    p, counts[4];
21316f5f1567SToby Isaac     PetscInt    *coneSizes, *cones, *orientations;
21326f5f1567SToby Isaac     Vec         coordVec;
21336f5f1567SToby Isaac     PetscScalar *coords;
21346f5f1567SToby Isaac 
21356f5f1567SToby Isaac     for (d = 0; d <= dim; d++) {
21366f5f1567SToby Isaac       PetscInt dStart, dEnd;
21376f5f1567SToby Isaac 
21386f5f1567SToby Isaac       ierr = DMPlexGetDepthStratum(dm,d,&dStart,&dEnd);CHKERRQ(ierr);
21396f5f1567SToby Isaac       counts[d] = dEnd - dStart;
21406f5f1567SToby Isaac     }
21416f5f1567SToby Isaac     ierr = PetscMalloc1(pEnd-pStart,&coneSizes);CHKERRQ(ierr);
21426f5f1567SToby Isaac     for (p = pStart; p < pEnd; p++) {
21436f5f1567SToby Isaac       ierr = DMPlexGetConeSize(dm,p,&coneSizes[p-pStart]);CHKERRQ(ierr);
21446f5f1567SToby Isaac     }
21456f5f1567SToby Isaac     ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr);
21466f5f1567SToby Isaac     ierr = DMPlexGetConeOrientations(dm, &orientations);CHKERRQ(ierr);
21476f5f1567SToby Isaac     ierr = DMGetCoordinatesLocal(dm,&coordVec);CHKERRQ(ierr);
21486f5f1567SToby Isaac     ierr = VecGetArray(coordVec,&coords);CHKERRQ(ierr);
21496f5f1567SToby Isaac 
21506f5f1567SToby Isaac     ierr = PetscSectionSetChart(parentSection,pStart,pEnd);CHKERRQ(ierr);
21516f5f1567SToby Isaac     ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr);
21526f5f1567SToby Isaac     ierr = DMPlexCreateFromDAG(*ncdm,dim,counts,coneSizes,cones,orientations,NULL);CHKERRQ(ierr);
21536f5f1567SToby Isaac     ierr = DMPlexSetReferenceTree(*ncdm,K);CHKERRQ(ierr);
21546f5f1567SToby Isaac     ierr = DMPlexSetTree(*ncdm,parentSection,NULL,NULL);CHKERRQ(ierr);
21556f5f1567SToby Isaac     ierr = VecRestoreArray(coordVec,&coords);CHKERRQ(ierr);
21566f5f1567SToby Isaac   }
21576f5f1567SToby Isaac   ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr);
21586f5f1567SToby Isaac 
21596f5f1567SToby Isaac   PetscFunctionReturn(0);
21606f5f1567SToby Isaac }
21616ecaa68aSToby Isaac 
21626ecaa68aSToby Isaac PETSC_EXTERN PetscErrorCode indicesPointFields_private(PetscSection,PetscInt,PetscInt,PetscInt[],PetscBool,PetscInt,PetscInt[]);
21636ecaa68aSToby Isaac PETSC_EXTERN PetscErrorCode indicesPoint_private(PetscSection,PetscInt,PetscInt,PetscInt *,PetscBool,PetscInt,PetscInt[]);
21646ecaa68aSToby Isaac #undef __FUNCT__
21656ecaa68aSToby Isaac #define __FUNCT__ "DMPlexComputeInterpolatorTree"
21666ecaa68aSToby Isaac PetscErrorCode DMPlexComputeInterpolatorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat)
21676ecaa68aSToby Isaac {
21686ecaa68aSToby Isaac   PetscSF        coarseToFineEmbedded;
21696ecaa68aSToby Isaac   DM             refTree;
21706ecaa68aSToby Isaac   PetscSection   globalCoarse, globalFine;
21716ecaa68aSToby Isaac   PetscSection   localCoarse, localFine;
21726ecaa68aSToby Isaac   PetscSection   aSec, cSec;
21736ecaa68aSToby Isaac   PetscSection   rootIndicesSec, rootMatricesSec;
2174*46bdb399SToby Isaac   PetscSection   leafIndicesSec, leafMatricesSec;
2175*46bdb399SToby Isaac   PetscInt       *rootIndices, *leafIndices;
2176*46bdb399SToby Isaac   PetscScalar    *rootMatrices, *leafMatrices;
21776ecaa68aSToby Isaac   IS             aIS;
21786ecaa68aSToby Isaac   const PetscInt *anchors;
21796ecaa68aSToby Isaac   Mat            cMat;
21806ecaa68aSToby Isaac   PetscInt       numFields;
21816ecaa68aSToby Isaac   PetscInt       pStartC, pEndC, pStartF, pEndF, p;
21826ecaa68aSToby Isaac   PetscInt       aStart, aEnd, cStart, cEnd;
21836ecaa68aSToby Isaac   PetscBool      *maxChildIds;
21846ecaa68aSToby Isaac   PetscErrorCode ierr;
21856ecaa68aSToby Isaac 
21866ecaa68aSToby Isaac   /*
21876ecaa68aSToby Isaac    * - communicate back to the coarse mesh which coarse points have children
21886ecaa68aSToby Isaac    * - for each coarse point:
21896ecaa68aSToby Isaac    *   - if the point has children or the point has anchors;
21906ecaa68aSToby Isaac    *     - compute the closure+anchor matrix for this point and global dofs from which to interpolate
21916ecaa68aSToby Isaac    *     - count the global dofs as sizeIndices
21926ecaa68aSToby Isaac    *     - if the closure+anchor matrix is not identity:
21936ecaa68aSToby Isaac    *       - count its size as sizeMatrix
21946ecaa68aSToby Isaac    *       else:
21956ecaa68aSToby Isaac    *       - sizeMatrix = 0
21966ecaa68aSToby Isaac    *     else:
21976ecaa68aSToby Isaac    *     - compute the indices for this point's global dofs, set to sizeIndices
21986ecaa68aSToby Isaac    *     - sizeMatrix = 0
21996ecaa68aSToby Isaac    * - calculate sections for sizeIndices and sizeMatrix and distribute them with the sf
22006ecaa68aSToby Isaac    * - for each fine point with global dofs:
22016ecaa68aSToby Isaac    *   - if this is not a child and sizeIndices == this point's number of global dofs:
22026ecaa68aSToby Isaac    *     - insert identity into the interpolator
22036ecaa68aSToby Isaac    *     else:
22046ecaa68aSToby Isaac    *     - if this is a child:
22056ecaa68aSToby Isaac    *       - multiply the incoming matrix by the parent-to-child matrix, then insert
22066ecaa68aSToby Isaac    *       else:
22076ecaa68aSToby Isaac    *       - insert the incoming matrix into the interpolator directly
22086ecaa68aSToby Isaac    */
22096ecaa68aSToby Isaac   PetscFunctionBegin;
22106ecaa68aSToby Isaac   ierr = DMPlexGetChart(coarse,&pStartC,&pEndC);CHKERRQ(ierr);
22116ecaa68aSToby Isaac   ierr = DMPlexGetChart(fine,&pStartF,&pEndF);CHKERRQ(ierr);
22126ecaa68aSToby Isaac   ierr = DMGetDefaultGlobalSection(fine,&globalFine);CHKERRQ(ierr);
22136ecaa68aSToby Isaac   { /* winnow fine points that don't have global dofs out of the sf */
22146ecaa68aSToby Isaac     PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs;
22156ecaa68aSToby Isaac 
22166ecaa68aSToby Isaac     for (p = pStartF, numPointsWithDofs = 0; p < pEndF; p++) {
22176ecaa68aSToby Isaac       ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr);
22186ecaa68aSToby Isaac       ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr);
22196ecaa68aSToby Isaac       if ((dof - cdof) > 0) {
22206ecaa68aSToby Isaac         numPointsWithDofs++;
22216ecaa68aSToby Isaac       }
22226ecaa68aSToby Isaac     }
22236ecaa68aSToby Isaac     ierr = PetscMalloc1(numPointsWithDofs,&pointsWithDofs);CHKERRQ(ierr);
22246ecaa68aSToby Isaac     for (p = pStartF, offset = 0; p < pEndF; p++) {
22256ecaa68aSToby Isaac       ierr = PetscSectionGetDof(globalFine,p,&dof);CHKERRQ(ierr);
22266ecaa68aSToby Isaac       ierr = PetscSectionGetConstraintDof(globalFine,p,&cdof);CHKERRQ(ierr);
22276ecaa68aSToby Isaac       if ((dof - cdof) > 0) {
22286ecaa68aSToby Isaac         pointsWithDofs[offset++] = p - pStartF;
22296ecaa68aSToby Isaac       }
22306ecaa68aSToby Isaac     }
22316ecaa68aSToby Isaac     ierr = PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded);CHKERRQ(ierr);
22326ecaa68aSToby Isaac   }
22336ecaa68aSToby Isaac   /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */
22346ecaa68aSToby Isaac   ierr = PetscMalloc1(pEndC-pStartC,&maxChildIds);CHKERRQ(ierr);
22356ecaa68aSToby Isaac   for (p = pStartC; p < pEndC; p++) {
22366ecaa68aSToby Isaac     maxChildIds[p - pStartC] = -1;
22376ecaa68aSToby Isaac   }
22386ecaa68aSToby Isaac   ierr = PetscSFReduceBegin(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX);CHKERRQ(ierr);
22396ecaa68aSToby Isaac   ierr = PetscSFReduceEnd(coarseToFineEmbedded,MPIU_INT,childIds,maxChildIds,MPIU_MAX);CHKERRQ(ierr);
2240*46bdb399SToby Isaac 
22416ecaa68aSToby Isaac   ierr = DMGetDefaultSection(coarse,&localCoarse);CHKERRQ(ierr);
22426ecaa68aSToby Isaac   ierr = DMGetDefaultGlobalSection(coarse,&globalCoarse);CHKERRQ(ierr);
2243*46bdb399SToby Isaac 
22446ecaa68aSToby Isaac   ierr = DMPlexGetAnchors(coarse,&aSec,&aIS);CHKERRQ(ierr);
22456ecaa68aSToby Isaac   ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr);
22466ecaa68aSToby Isaac   ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr);
2247*46bdb399SToby Isaac 
22486ecaa68aSToby Isaac   ierr = DMGetDefaultConstraints(coarse,&cSec,&cMat);CHKERRQ(ierr);
22496ecaa68aSToby Isaac   ierr = PetscSectionGetChart(cSec,&cStart,&cEnd);CHKERRQ(ierr);
2250*46bdb399SToby Isaac 
2251*46bdb399SToby Isaac   /* create sections that will send to children the indices and matrices they will need to construct the interpolator */
22526ecaa68aSToby Isaac   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootIndicesSec);CHKERRQ(ierr);
22536ecaa68aSToby Isaac   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)coarse),&rootMatricesSec);CHKERRQ(ierr);
22546ecaa68aSToby Isaac   ierr = PetscSectionSetChart(rootIndicesSec,pStartC,pEndC);CHKERRQ(ierr);
22556ecaa68aSToby Isaac   ierr = PetscSectionSetChart(rootMatricesSec,pStartC,pEndC);CHKERRQ(ierr);
22566ecaa68aSToby Isaac   ierr = PetscSectionGetNumFields(globalCoarse,&numFields);CHKERRQ(ierr);
2257*46bdb399SToby Isaac 
2258*46bdb399SToby Isaac   for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */
22596ecaa68aSToby Isaac     PetscInt dof, matSize;
22606ecaa68aSToby Isaac     PetscInt aDof           = 0;
22616ecaa68aSToby Isaac     PetscInt cDof           = 0;
22626ecaa68aSToby Isaac     PetscInt maxChildId     = maxChildIds[p - pStartC];
22636ecaa68aSToby Isaac     PetscInt numRowIndices  = 0;
22646ecaa68aSToby Isaac     PetscInt numColIndices  = 0;
22656ecaa68aSToby Isaac     PetscInt offsets[32]    = {0};
22666ecaa68aSToby Isaac     PetscInt newOffsets[32] = {0};
22676ecaa68aSToby Isaac 
22686ecaa68aSToby Isaac     ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr);
22696ecaa68aSToby Isaac     if (p >= aStart && p < aEnd) {
22706ecaa68aSToby Isaac       ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr);
22716ecaa68aSToby Isaac     }
22726ecaa68aSToby Isaac     if (p >= cStart && p < cEnd) {
22736ecaa68aSToby Isaac       ierr = PetscSectionGetDof(cSec,p,&cDof);CHKERRQ(ierr);
22746ecaa68aSToby Isaac     }
22756ecaa68aSToby Isaac     if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */
22766ecaa68aSToby Isaac       PetscInt *closure = NULL, closureSize, cl, f;
22776ecaa68aSToby Isaac 
22786ecaa68aSToby Isaac       ierr = DMPlexGetTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
2279*46bdb399SToby Isaac       for (cl = 0; cl < closureSize; cl++) { /* get the closure */
22806ecaa68aSToby Isaac         PetscInt c = closure[2 * cl], clDof;
22816ecaa68aSToby Isaac 
22826ecaa68aSToby Isaac         ierr = PetscSectionGetDof(localCoarse,c,&clDof);CHKERRQ(ierr);
22836ecaa68aSToby Isaac         numRowIndices += clDof;
22846ecaa68aSToby Isaac         for (f = 0; f < numFields; f++) {
22856ecaa68aSToby Isaac           ierr = PetscSectionGetFieldDof(localCoarse,c,f,&clDof);CHKERRQ(ierr);
22866ecaa68aSToby Isaac           offsets[f + 1] += clDof;
22876ecaa68aSToby Isaac         }
22886ecaa68aSToby Isaac       }
22896ecaa68aSToby Isaac       for (f = 0; f < numFields; f++) {
22906ecaa68aSToby Isaac         offsets[f + 1] += offsets[f];
22916ecaa68aSToby Isaac         newOffsets[f + 1] = offsets[f + 1];
22926ecaa68aSToby Isaac       }
2293*46bdb399SToby Isaac       /* get the number of indices needed and their field offsets */
22946ecaa68aSToby Isaac       ierr = DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,NULL,NULL,&numColIndices,NULL,NULL,newOffsets,PETSC_FALSE);CHKERRQ(ierr);
22956ecaa68aSToby Isaac       ierr = DMPlexRestoreTransitiveClosure(coarse,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr);
22966ecaa68aSToby Isaac       if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */
22976ecaa68aSToby Isaac         numColIndices = numRowIndices;
22986ecaa68aSToby Isaac         matSize = 0;
22996ecaa68aSToby Isaac       }
2300*46bdb399SToby Isaac       else if (numFields) { /* we send one submat for each field: sum their sizes */
23016ecaa68aSToby Isaac         matSize = 0;
23026ecaa68aSToby Isaac         for (f = 0; f < numFields; f++) {
23036ecaa68aSToby Isaac           PetscInt numRow, numCol;
23046ecaa68aSToby Isaac 
23056ecaa68aSToby Isaac           numRow = offsets[f + 1] - offsets[f];
23066ecaa68aSToby Isaac           numCol = newOffsets[f + 1] - newOffsets[f + 1];
23076ecaa68aSToby Isaac           matSize += numRow * numCol;
23086ecaa68aSToby Isaac         }
23096ecaa68aSToby Isaac       }
23106ecaa68aSToby Isaac       else {
23116ecaa68aSToby Isaac         matSize = numRowIndices * numColIndices;
23126ecaa68aSToby Isaac       }
23136ecaa68aSToby Isaac     }
23146ecaa68aSToby Isaac     else if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */
23156ecaa68aSToby Isaac       PetscInt aOff, a, f;
23166ecaa68aSToby Isaac 
23176ecaa68aSToby Isaac       ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr);
23186ecaa68aSToby Isaac       for (f = 0; f < numFields; f++) {
23196ecaa68aSToby Isaac         PetscInt fDof;
23206ecaa68aSToby Isaac 
23216ecaa68aSToby Isaac         ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr);
23226ecaa68aSToby Isaac         offsets[f] = fDof;
23236ecaa68aSToby Isaac       }
23246ecaa68aSToby Isaac       for (a = 0; a < aDof; a++) {
23256ecaa68aSToby Isaac         PetscInt anchor = anchors[a + aOff], aLocalDof;
23266ecaa68aSToby Isaac 
23276ecaa68aSToby Isaac         ierr = PetscSectionGetDof(localCoarse,anchor,&aLocalDof);CHKERRQ(ierr);
23286ecaa68aSToby Isaac         numColIndices += aLocalDof;
23296ecaa68aSToby Isaac         for (f = 0; f < numFields; f++) {
23306ecaa68aSToby Isaac           PetscInt fDof;
23316ecaa68aSToby Isaac 
23326ecaa68aSToby Isaac           ierr = PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof);CHKERRQ(ierr);
23336ecaa68aSToby Isaac           newOffsets[f] += fDof;
23346ecaa68aSToby Isaac         }
23356ecaa68aSToby Isaac       }
23366ecaa68aSToby Isaac       if (numFields) {
23376ecaa68aSToby Isaac         matSize = 0;
23386ecaa68aSToby Isaac         for (f = 0; f < numFields; f++) {
23396ecaa68aSToby Isaac           matSize += offsets[f] * newOffsets[f];
23406ecaa68aSToby Isaac         }
23416ecaa68aSToby Isaac       }
23426ecaa68aSToby Isaac       else {
23436ecaa68aSToby Isaac         matSize = numColIndices * dof;
23446ecaa68aSToby Isaac       }
23456ecaa68aSToby Isaac     }
23466ecaa68aSToby Isaac     else { /* no children, and no constraints on dofs: just get the global indices */
23476ecaa68aSToby Isaac       numColIndices = dof;
23486ecaa68aSToby Isaac       matSize       = 0;
23496ecaa68aSToby Isaac     }
2350*46bdb399SToby Isaac     /* we will pack the column indices with the field offsets */
23516ecaa68aSToby Isaac     ierr = PetscSectionSetDof(rootIndicesSec,p,numColIndices ? numColIndices+2*numFields : 0);CHKERRQ(ierr);
23526ecaa68aSToby Isaac     ierr = PetscSectionSetDof(rootMatricesSec,p,matSize);CHKERRQ(ierr);
23536ecaa68aSToby Isaac   }
23546ecaa68aSToby Isaac   ierr = PetscSectionSetUp(rootIndicesSec);CHKERRQ(ierr);
23556ecaa68aSToby Isaac   ierr = PetscSectionSetUp(rootMatricesSec);CHKERRQ(ierr);
23566ecaa68aSToby Isaac   {
23576ecaa68aSToby Isaac     PetscInt    numRootIndices, numRootMatrices;
23586ecaa68aSToby Isaac 
23596ecaa68aSToby Isaac     ierr = PetscSectionGetStorageSize(rootIndicesSec,&numRootIndices);CHKERRQ(ierr);
23606ecaa68aSToby Isaac     ierr = PetscSectionGetStorageSize(rootMatricesSec,&numRootMatrices);CHKERRQ(ierr);
23616ecaa68aSToby Isaac     ierr = PetscMalloc2(numRootIndices,&rootIndices,numRootMatrices,&rootMatrices);CHKERRQ(ierr);
23626ecaa68aSToby Isaac     for (p = pStartC; p < pEndC; p++) {
23636ecaa68aSToby Isaac       PetscInt    numRowIndices, numColIndices, matSize, dof;
23646ecaa68aSToby Isaac       PetscInt    pIndOff, pMatOff;
23656ecaa68aSToby Isaac       PetscInt    *pInd;
23666ecaa68aSToby Isaac       PetscInt    maxChildId = maxChildIds[p - pStartC];
23676ecaa68aSToby Isaac       PetscInt    offsets[32] = {0}, newOffsets[32] = {0};
23686ecaa68aSToby Isaac       PetscScalar *pMat = NULL;
23696ecaa68aSToby Isaac 
23706ecaa68aSToby Isaac       ierr = PetscSectionGetDof(rootIndicesSec,p,&numColIndices);CHKERRQ(ierr);
23716ecaa68aSToby Isaac       if (!numColIndices) {
23726ecaa68aSToby Isaac         continue;
23736ecaa68aSToby Isaac       }
23746ecaa68aSToby Isaac       numColIndices -= 2 * numFields;
23756ecaa68aSToby Isaac       ierr = PetscSectionGetOffset(rootIndicesSec,p,&pIndOff);CHKERRQ(ierr);
23766ecaa68aSToby Isaac       pInd = &(rootIndices[pIndOff]);
23776ecaa68aSToby Isaac       ierr = PetscSectionGetDof(rootMatricesSec,p,&matSize);CHKERRQ(ierr);
23786ecaa68aSToby Isaac       if (matSize) {
23796ecaa68aSToby Isaac         ierr = PetscSectionGetOffset(rootMatricesSec,p,&pMatOff);CHKERRQ(ierr);
23806ecaa68aSToby Isaac         pMat = &rootMatrices[pMatOff];
23816ecaa68aSToby Isaac       }
23826ecaa68aSToby Isaac       ierr = PetscSectionGetDof(globalCoarse,p,&dof);CHKERRQ(ierr);
23836ecaa68aSToby Isaac       if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */
23846ecaa68aSToby Isaac         PetscInt i, j;
23856ecaa68aSToby Isaac         PetscInt numRowIndices = matSize / numColIndices;
23866ecaa68aSToby Isaac 
23876ecaa68aSToby Isaac         if (!numRowIndices) { /* don't need to calculate the mat, just the indices */
23886ecaa68aSToby Isaac           PetscInt numIndices, *indices;
23896ecaa68aSToby Isaac           ierr = DMPlexGetClosureIndices(coarse,localCoarse,globalCoarse,p,&numIndices,&indices,offsets);CHKERRQ(ierr);
23906ecaa68aSToby Isaac           if (numIndices != numColIndices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"mismatching constraint indices calculations");
23916ecaa68aSToby Isaac           for (i = 0; i < numColIndices; i++) {
23926ecaa68aSToby Isaac             pInd[i] = indices[i];
23936ecaa68aSToby Isaac           }
23946ecaa68aSToby Isaac           for (i = 0; i < numFields; i++) {
2395*46bdb399SToby Isaac             pInd[numColIndices + i]             = offsets[i+1];
2396*46bdb399SToby Isaac             pInd[numColIndices + numFields + i] = offsets[i+1];
23976ecaa68aSToby Isaac           }
2398*46bdb399SToby Isaac           ierr = DMPlexRestoreClosureIndices(coarse,localCoarse,globalCoarse,p,&numIndices,&indices,offsets);CHKERRQ(ierr);
23996ecaa68aSToby Isaac         }
24006ecaa68aSToby Isaac         else {
24016ecaa68aSToby Isaac           PetscInt closureSize, *closure = NULL, cl;
24026ecaa68aSToby Isaac           PetscScalar *pMatIn, *pMatModified;
24036ecaa68aSToby Isaac           PetscInt numPoints,*points;
24046ecaa68aSToby Isaac 
24056ecaa68aSToby Isaac           ierr = DMGetWorkArray(coarse,numRowIndices * numRowIndices,PETSC_SCALAR,&pMatIn);CHKERRQ(ierr);
24066ecaa68aSToby Isaac           for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */
24076ecaa68aSToby Isaac             for (j = 0; j < numRowIndices; j++) {
24086ecaa68aSToby Isaac               pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.;
24096ecaa68aSToby Isaac             }
24106ecaa68aSToby Isaac           }
24116ecaa68aSToby Isaac           ierr = DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
24126ecaa68aSToby Isaac           if (numFields) {
24136ecaa68aSToby Isaac             PetscInt f;
24146ecaa68aSToby Isaac 
24156ecaa68aSToby Isaac             for (cl = 0; cl < closureSize; cl++) {
24166ecaa68aSToby Isaac               PetscInt c = closure[2 * cl];
24176ecaa68aSToby Isaac 
24186ecaa68aSToby Isaac               for (f = 0; f < numFields; f++) {
24196ecaa68aSToby Isaac                 PetscInt fDof;
24206ecaa68aSToby Isaac 
24216ecaa68aSToby Isaac                 ierr = PetscSectionGetFieldDof(localCoarse,c,f,&fDof);CHKERRQ(ierr);
24226ecaa68aSToby Isaac                 offsets[f + 1] += fDof;
24236ecaa68aSToby Isaac               }
24246ecaa68aSToby Isaac             }
24256ecaa68aSToby Isaac             for (f = 0; f < numFields; f++) {
24266ecaa68aSToby Isaac               offsets[f + 1]   += offsets[f];
24276ecaa68aSToby Isaac               newOffsets[f + 1] = offsets[f + 1];
24286ecaa68aSToby Isaac             }
24296ecaa68aSToby Isaac           }
24306ecaa68aSToby Isaac           /* apply hanging node constraints on the right, get the new points and the new offsets */
24316ecaa68aSToby Isaac           ierr = DMPlexAnchorsModifyMat(coarse,localCoarse,closureSize,numRowIndices,closure,pMat,&numPoints,NULL,&points,&pMatModified,newOffsets,PETSC_FALSE);CHKERRQ(ierr);
24326ecaa68aSToby Isaac           if (!numFields) {
24336ecaa68aSToby Isaac             for (i = 0; i < numRowIndices * numColIndices; i++) {
24346ecaa68aSToby Isaac               pMat[i] = pMatModified[i];
24356ecaa68aSToby Isaac             }
24366ecaa68aSToby Isaac           }
24376ecaa68aSToby Isaac           else {
24386ecaa68aSToby Isaac             PetscInt f, i, j, count;
24396ecaa68aSToby Isaac             for (f = 0, count = 0; f < numFields; f++) {
24406ecaa68aSToby Isaac               for (i = offsets[f]; i < offsets[f+1]; i++) {
24416ecaa68aSToby Isaac                 for (j = newOffsets[f]; j < newOffsets[f+1]; j++, count++) {
24426ecaa68aSToby Isaac                   pMat[count] = pMatModified[i * numColIndices + j];
24436ecaa68aSToby Isaac                 }
24446ecaa68aSToby Isaac               }
24456ecaa68aSToby Isaac             }
24466ecaa68aSToby Isaac           }
24476ecaa68aSToby Isaac           ierr = DMRestoreWorkArray(coarse,numRowIndices * numColIndices,PETSC_SCALAR,&pMatModified);CHKERRQ(ierr);
24486ecaa68aSToby Isaac           ierr = DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
24496ecaa68aSToby Isaac           ierr = DMRestoreWorkArray(coarse,numRowIndices * numColIndices,PETSC_SCALAR,&pMatIn);CHKERRQ(ierr);
24506ecaa68aSToby Isaac           if (numFields) {
2451*46bdb399SToby Isaac             PetscInt f;
2452*46bdb399SToby Isaac             for (f = 0; f < numFields; f++) {
2453*46bdb399SToby Isaac               pInd[numColIndices + f]             = offsets[f+1];
2454*46bdb399SToby Isaac               pInd[numColIndices + numFields + f] = newOffsets[f+1];
24556ecaa68aSToby Isaac             }
24566ecaa68aSToby Isaac             for (cl = 0; cl < numPoints*2; cl += 2) {
24576ecaa68aSToby Isaac               PetscInt o = points[cl+1], globalOff, c = points[cl];
24586ecaa68aSToby Isaac               ierr = PetscSectionGetOffset(globalCoarse, c, &globalOff);CHKERRQ(ierr);
2459*46bdb399SToby Isaac               indicesPointFields_private(localCoarse, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, o, pInd);
24606ecaa68aSToby Isaac             }
24616ecaa68aSToby Isaac           } else {
24626ecaa68aSToby Isaac             for (cl = 0; cl < numPoints*2; cl += 2) {
24636ecaa68aSToby Isaac               PetscInt o = points[cl+1], c = points[cl], globalOff;
24646ecaa68aSToby Isaac               ierr = PetscSectionGetOffset(globalCoarse, c, &globalOff);CHKERRQ(ierr);
24656ecaa68aSToby Isaac               newOffsets[0] = 0;
24666ecaa68aSToby Isaac               indicesPoint_private(localCoarse, c, globalOff < 0 ? -(globalOff+1) : globalOff, newOffsets, PETSC_FALSE, o, pInd);
24676ecaa68aSToby Isaac             }
24686ecaa68aSToby Isaac           }
24696ecaa68aSToby Isaac         }
24706ecaa68aSToby Isaac       }
24716ecaa68aSToby Isaac       else if (matSize) {
24726ecaa68aSToby Isaac         PetscInt cOff;
24736ecaa68aSToby Isaac         PetscInt *rowIndices, *colIndices, a, aDof, aOff;
24746ecaa68aSToby Isaac 
24756ecaa68aSToby Isaac         numRowIndices = matSize / numColIndices;
24766ecaa68aSToby Isaac         if (!numRowIndices != dof) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Miscounted dofs");
24776ecaa68aSToby Isaac         ierr = DMGetWorkArray(coarse,numRowIndices,PETSC_INT,&rowIndices);CHKERRQ(ierr);
24786ecaa68aSToby Isaac         ierr = DMGetWorkArray(coarse,numColIndices,PETSC_INT,&colIndices);CHKERRQ(ierr);
24796ecaa68aSToby Isaac         ierr = PetscSectionGetOffset(cSec,p,&cOff);CHKERRQ(ierr);
24806ecaa68aSToby Isaac         ierr = PetscSectionGetDof(aSec,p,&aDof);CHKERRQ(ierr);
24816ecaa68aSToby Isaac         ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr);
24826ecaa68aSToby Isaac         if (numFields) {
24836ecaa68aSToby Isaac           PetscInt f;
24846ecaa68aSToby Isaac           PetscInt offsetsCopy[32] = {0};
24856ecaa68aSToby Isaac           PetscInt newOffsetsCopy[32] = {0};
24866ecaa68aSToby Isaac 
24876ecaa68aSToby Isaac           for (f = 0; f < numFields; f++) {
24886ecaa68aSToby Isaac             PetscInt fDof;
24896ecaa68aSToby Isaac             ierr = PetscSectionGetFieldDof(cSec,p,f,&fDof);CHKERRQ(ierr);
24906ecaa68aSToby Isaac             offsets[f + 1] = fDof;
24916ecaa68aSToby Isaac             for (a = 0; a < aDof; a++) {
24926ecaa68aSToby Isaac               PetscInt anchor = anchors[a + aOff];
24936ecaa68aSToby Isaac               ierr = PetscSectionGetFieldDof(localCoarse,anchor,f,&fDof);CHKERRQ(ierr);
24946ecaa68aSToby Isaac               newOffsets[f + 1] += fDof;
24956ecaa68aSToby Isaac             }
24966ecaa68aSToby Isaac           }
24976ecaa68aSToby Isaac           for (f = 0; f < numFields; f++) {
24986ecaa68aSToby Isaac             offsets[f + 1]       += offsets[f];
24996ecaa68aSToby Isaac             offsetsCopy[f + 1]    = offsets[f + 1];
25006ecaa68aSToby Isaac             newOffsets[f + 1]    += newOffsets[f];
25016ecaa68aSToby Isaac             newOffsetsCopy[f + 1] = newOffsets[f + 1];
25026ecaa68aSToby Isaac           }
25036ecaa68aSToby Isaac           indicesPointFields_private(cSec,p,cOff,offsetsCopy,PETSC_TRUE,0,rowIndices);CHKERRQ(ierr);
25046ecaa68aSToby Isaac           for (a = 0; a < aDof; a++) {
25056ecaa68aSToby Isaac             PetscInt anchor = anchors[a + aOff], lOff;
25066ecaa68aSToby Isaac             ierr = PetscSectionGetOffset(localCoarse,anchor,&lOff);CHKERRQ(ierr);
25076ecaa68aSToby Isaac             indicesPointFields_private(localCoarse,anchor,lOff,offsetsCopy,PETSC_TRUE,0,colIndices);CHKERRQ(ierr);
25086ecaa68aSToby Isaac           }
25096ecaa68aSToby Isaac         }
25106ecaa68aSToby Isaac         else {
25116ecaa68aSToby Isaac           indicesPoint_private(cSec,p,cOff,offsets,PETSC_TRUE,0,rowIndices);CHKERRQ(ierr);
25126ecaa68aSToby Isaac           for (a = 0; a < aDof; a++) {
25136ecaa68aSToby Isaac             PetscInt anchor = anchors[a + aOff], lOff;
25146ecaa68aSToby Isaac             ierr = PetscSectionGetOffset(localCoarse,anchor,&lOff);CHKERRQ(ierr);
25156ecaa68aSToby Isaac             indicesPoint_private(localCoarse,anchor,lOff,newOffsets,PETSC_TRUE,0,colIndices);CHKERRQ(ierr);
25166ecaa68aSToby Isaac           }
25176ecaa68aSToby Isaac         }
25186ecaa68aSToby Isaac         if (numFields) {
25196ecaa68aSToby Isaac           PetscInt count, f, a;
25206ecaa68aSToby Isaac           for (f = 0, count = 0; f < numFields; f++) {
25216ecaa68aSToby Isaac             PetscInt iSize = offsets[f + 1] - offsets[f];
25226ecaa68aSToby Isaac             PetscInt jSize = newOffsets[f + 1] - newOffsets[f];
25236ecaa68aSToby Isaac             ierr = MatGetValues(cMat,iSize,&rowIndices[offsets[f]],jSize,&colIndices[newOffsets[f]],&pMat[count]);CHKERRQ(ierr);
25246ecaa68aSToby Isaac             count += iSize * jSize;
2525*46bdb399SToby Isaac             pInd[numColIndices + f]             = offsets[f+1];
2526*46bdb399SToby Isaac             pInd[numColIndices + numFields + f] = newOffsets[f+1];
25276ecaa68aSToby Isaac           }
25286ecaa68aSToby Isaac           for (a = 0; a < aDof; a++) {
25296ecaa68aSToby Isaac             PetscInt anchor = anchors[a + aOff];
25306ecaa68aSToby Isaac             PetscInt gOff;
25316ecaa68aSToby Isaac             ierr = PetscSectionGetOffset(globalCoarse,anchor,&gOff);CHKERRQ(ierr);
25326ecaa68aSToby Isaac             indicesPointFields_private(localCoarse,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr);
25336ecaa68aSToby Isaac           }
25346ecaa68aSToby Isaac         }
25356ecaa68aSToby Isaac         else {
25366ecaa68aSToby Isaac           PetscInt a;
25376ecaa68aSToby Isaac           ierr = MatGetValues(cMat,numRowIndices,rowIndices,numColIndices,colIndices,pMat);CHKERRQ(ierr);
25386ecaa68aSToby Isaac           for (a = 0; a < aDof; a++) {
25396ecaa68aSToby Isaac             PetscInt anchor = anchors[a + aOff];
25406ecaa68aSToby Isaac             PetscInt gOff;
25416ecaa68aSToby Isaac             ierr = PetscSectionGetOffset(globalCoarse,anchor,&gOff);CHKERRQ(ierr);
25426ecaa68aSToby Isaac             newOffsets[0] = 0;
25436ecaa68aSToby Isaac             indicesPoint_private(localCoarse,anchor,gOff < 0 ? -(gOff + 1) : gOff,newOffsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr);
25446ecaa68aSToby Isaac           }
25456ecaa68aSToby Isaac         }
25466ecaa68aSToby Isaac         ierr = DMRestoreWorkArray(coarse,numColIndices,PETSC_INT,&colIndices);CHKERRQ(ierr);
25476ecaa68aSToby Isaac         ierr = DMRestoreWorkArray(coarse,numRowIndices,PETSC_INT,&rowIndices);CHKERRQ(ierr);
25486ecaa68aSToby Isaac       }
25496ecaa68aSToby Isaac       else {
25506ecaa68aSToby Isaac         PetscInt gOff;
25516ecaa68aSToby Isaac 
25526ecaa68aSToby Isaac         ierr = PetscSectionGetOffset(globalCoarse,p,&gOff);CHKERRQ(ierr);
25536ecaa68aSToby Isaac         if (numFields) {
25546ecaa68aSToby Isaac           PetscInt f;
25556ecaa68aSToby Isaac 
25566ecaa68aSToby Isaac           for (f = 0; f < numFields; f++) {
25576ecaa68aSToby Isaac             PetscInt fDof;
25586ecaa68aSToby Isaac             ierr = PetscSectionGetFieldDof(localCoarse,p,f,&fDof);CHKERRQ(ierr);
25596ecaa68aSToby Isaac             offsets[f + 1] = fDof + offsets[f];
25606ecaa68aSToby Isaac           }
25616ecaa68aSToby Isaac           for (f = 0; f < numFields; f++) {
2562*46bdb399SToby Isaac             pInd[numColIndices + f]             = offsets[f+1];
2563*46bdb399SToby Isaac             pInd[numColIndices + numFields + f] = offsets[f+1];
25646ecaa68aSToby Isaac           }
25656ecaa68aSToby Isaac           indicesPointFields_private(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr);
25666ecaa68aSToby Isaac         }
25676ecaa68aSToby Isaac         else {
25686ecaa68aSToby Isaac           indicesPoint_private(localCoarse,p,gOff < 0 ? -(gOff + 1) : gOff,offsets,PETSC_FALSE,0,pInd);CHKERRQ(ierr);
25696ecaa68aSToby Isaac         }
25706ecaa68aSToby Isaac       }
25716ecaa68aSToby Isaac     }
25726ecaa68aSToby Isaac   }
2573*46bdb399SToby Isaac   {
2574*46bdb399SToby Isaac     PetscSF  indicesSF, matricesSF;
2575*46bdb399SToby Isaac     PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices;
2576*46bdb399SToby Isaac 
2577*46bdb399SToby Isaac     ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafIndicesSec);CHKERRQ(ierr);
2578*46bdb399SToby Isaac     ierr = PetscSectionCreate(PetscObjectComm((PetscObject)fine),&leafMatricesSec);CHKERRQ(ierr);
2579*46bdb399SToby Isaac     ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootIndicesSec,&remoteOffsetsIndices,leafIndicesSec);CHKERRQ(ierr);
2580*46bdb399SToby Isaac     ierr = PetscSFDistributeSection(coarseToFineEmbedded,rootMatricesSec,&remoteOffsetsMatrices,leafMatricesSec);CHKERRQ(ierr);
2581*46bdb399SToby Isaac     ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootIndicesSec,remoteOffsetsIndices,leafIndicesSec,&indicesSF);CHKERRQ(ierr);
2582*46bdb399SToby Isaac     ierr = PetscSFCreateSectionSF(coarseToFineEmbedded,rootMatricesSec,remoteOffsetsMatrices,leafMatricesSec,&matricesSF);CHKERRQ(ierr);
2583*46bdb399SToby Isaac     ierr = PetscFree(remoteOffsetsIndices);CHKERRQ(ierr);
2584*46bdb399SToby Isaac     ierr = PetscFree(remoteOffsetsMatrices);CHKERRQ(ierr);
2585*46bdb399SToby Isaac     ierr = PetscSectionGetStorageSize(leafIndicesSec,&numLeafIndices);CHKERRQ(ierr);
2586*46bdb399SToby Isaac     ierr = PetscSectionGetStorageSize(leafMatricesSec,&numLeafMatrices);CHKERRQ(ierr);
2587*46bdb399SToby Isaac     ierr = PetscMalloc2(numLeafIndices,&leafIndices,numLeafMatrices,&leafMatrices);CHKERRQ(ierr);
2588*46bdb399SToby Isaac     ierr = PetscSFBcastBegin(indicesSF,MPIU_INT,rootIndices,leafIndices);CHKERRQ(ierr);
2589*46bdb399SToby Isaac     ierr = PetscSFBcastBegin(matricesSF,MPIU_INT,rootMatrices,leafMatrices);CHKERRQ(ierr);
2590*46bdb399SToby Isaac     ierr = PetscSFBcastEnd(indicesSF,MPIU_INT,rootIndices,leafIndices);CHKERRQ(ierr);
2591*46bdb399SToby Isaac     ierr = PetscSFBcastEnd(matricesSF,MPIU_INT,rootMatrices,leafMatrices);CHKERRQ(ierr);
2592*46bdb399SToby Isaac     ierr = PetscSFDestroy(&matricesSF);CHKERRQ(ierr);
2593*46bdb399SToby Isaac     ierr = PetscSFDestroy(&indicesSF);CHKERRQ(ierr);
2594*46bdb399SToby Isaac     ierr = PetscFree2(rootIndices,rootMatrices);CHKERRQ(ierr);
2595*46bdb399SToby Isaac     ierr = PetscSectionDestroy(&rootIndicesSec);CHKERRQ(ierr);
2596*46bdb399SToby Isaac     ierr = PetscSectionDestroy(&rootMatricesSec);CHKERRQ(ierr);
2597*46bdb399SToby Isaac   }
2598*46bdb399SToby Isaac   /* count to preallocate */
2599*46bdb399SToby Isaac   ierr = DMGetDefaultSection(fine,&localFine);CHKERRQ(ierr);
2600*46bdb399SToby Isaac   {
2601*46bdb399SToby Isaac     PetscInt    nGlobal;
2602*46bdb399SToby Isaac     PetscInt    *dnnz, *onnz;
2603*46bdb399SToby Isaac     PetscLayout colMap;
2604*46bdb399SToby Isaac     PetscInt    colStart, colEnd;
2605*46bdb399SToby Isaac 
2606*46bdb399SToby Isaac     ierr = PetscSectionGetConstrainedStorageSize(globalFine,&nGlobal);CHKERRQ(ierr);
2607*46bdb399SToby Isaac     ierr = PetscCalloc2(nGlobal,&dnnz,nGlobal,&onnz);CHKERRQ(ierr);
2608*46bdb399SToby Isaac     ierr = MatGetLayouts(mat,NULL,&colMap);CHKERRQ(ierr);
2609*46bdb399SToby Isaac     ierr = PetscLayoutGetRange(colMap,&colStart,&colEnd);CHKERRQ(ierr);
2610*46bdb399SToby Isaac     for (p = pStartF; p < pEndF; p++) {
2611*46bdb399SToby Isaac       PetscInt    gDof, gcDof, gOff;
2612*46bdb399SToby Isaac       PetscInt    numColIndices, pIndOff, *pInd;
2613*46bdb399SToby Isaac       PetscInt    matSize;
2614*46bdb399SToby Isaac       PetscInt    numD = 0, numO = 0, i;
2615*46bdb399SToby Isaac       PetscInt    fNumD[32] = {0}, fNumO[32] = {0};
2616*46bdb399SToby Isaac       PetscInt    colOffsets[32] = {0}, rowOffsets[32] = {0};
2617*46bdb399SToby Isaac       PetscInt    *rowIndices;
2618*46bdb399SToby Isaac 
2619*46bdb399SToby Isaac       ierr = PetscSectionGetDof(globalFine,p,&gDof);CHKERRQ(ierr);
2620*46bdb399SToby Isaac       ierr = PetscSectionGetConstraintDof(globalFine,p,&gcDof);CHKERRQ(ierr);
2621*46bdb399SToby Isaac       if ((gDof - gcDof) <= 0) {
2622*46bdb399SToby Isaac         continue;
2623*46bdb399SToby Isaac       }
2624*46bdb399SToby Isaac       ierr = DMGetWorkArray(fine,gDof,PETSC_INT,&rowIndices);CHKERRQ(ierr);
2625*46bdb399SToby Isaac       ierr = PetscSectionGetOffset(globalFine,p,&gOff);CHKERRQ(ierr);
2626*46bdb399SToby Isaac       if (gOff < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"I though having global dofs meant a non-negative offset");
2627*46bdb399SToby Isaac       ierr = PetscSectionGetDof(leafIndicesSec,p,&numColIndices);CHKERRQ(ierr);
2628*46bdb399SToby Isaac       ierr = PetscSectionGetOffset(leafIndicesSec,p,&pIndOff);CHKERRQ(ierr);
2629*46bdb399SToby Isaac       numColIndices -= 2 * numFields;
2630*46bdb399SToby Isaac       if (!numColIndices <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"global find dof with no dofs to interpolate from");
2631*46bdb399SToby Isaac       pInd = &leafIndices[pIndOff];
2632*46bdb399SToby Isaac       if (numFields) {
2633*46bdb399SToby Isaac         PetscInt rowOffsetsCopy[32] = {0}, f;
2634*46bdb399SToby Isaac         for (f = 0; f < numFields; f++) {
2635*46bdb399SToby Isaac           PetscInt rowDof;
2636*46bdb399SToby Isaac 
2637*46bdb399SToby Isaac           ierr = PetscSectionGetFieldDof(localFine,p,f,&rowDof);CHKERRQ(ierr);
2638*46bdb399SToby Isaac           rowOffsets[f + 1]     = rowOffsets[f] + rowDof;
2639*46bdb399SToby Isaac           rowOffsetsCopy[f + 1] = rowOffsets[f + 1];
2640*46bdb399SToby Isaac           colOffsets[f + 1]     = pInd[numColIndices + numFields + f];
2641*46bdb399SToby Isaac         }
2642*46bdb399SToby Isaac         ierr = indicesPointFields_private(localFine,p,gOff,rowOffsetsCopy,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr);
2643*46bdb399SToby Isaac         for (f = 0; f < numFields; f++) {
2644*46bdb399SToby Isaac           PetscInt colOffset    = colOffsets[f];
2645*46bdb399SToby Isaac           PetscInt numFieldCols = colOffsets[f + 1] - colOffsets[f];
2646*46bdb399SToby Isaac 
2647*46bdb399SToby Isaac           for (i = 0; i < numFieldCols; i++) {
2648*46bdb399SToby Isaac             PetscInt gInd = pInd[i + colOffset];
2649*46bdb399SToby Isaac 
2650*46bdb399SToby Isaac             if (gInd >= colStart && gInd < colEnd) {
2651*46bdb399SToby Isaac               fNumD[f]++;
2652*46bdb399SToby Isaac             }
2653*46bdb399SToby Isaac             else if (gInd >= 0) { /* negative means non-entry */
2654*46bdb399SToby Isaac               fNumO[f]++;
2655*46bdb399SToby Isaac             }
2656*46bdb399SToby Isaac           }
2657*46bdb399SToby Isaac         }
2658*46bdb399SToby Isaac       }
2659*46bdb399SToby Isaac       else {
2660*46bdb399SToby Isaac         PetscInt offset = 0;
2661*46bdb399SToby Isaac         ierr = indicesPoint_private(localFine,p,gOff,&offset,PETSC_FALSE,0,rowIndices);CHKERRQ(ierr);
2662*46bdb399SToby Isaac         for (i = 0; i < numColIndices; i++) {
2663*46bdb399SToby Isaac           PetscInt gInd = pInd[i];
2664*46bdb399SToby Isaac 
2665*46bdb399SToby Isaac           if (gInd >= colStart && gInd < colEnd) {
2666*46bdb399SToby Isaac             numD++;
2667*46bdb399SToby Isaac           }
2668*46bdb399SToby Isaac           else if (gInd >= 0) { /* negative means non-entry */
2669*46bdb399SToby Isaac             numO++;
2670*46bdb399SToby Isaac           }
2671*46bdb399SToby Isaac         }
2672*46bdb399SToby Isaac       }
2673*46bdb399SToby Isaac       ierr = PetscSectionGetDof(leafMatricesSec,p,&matSize);CHKERRQ(ierr);
2674*46bdb399SToby Isaac       if (!matSize) { /* incoming matrix is identity */
2675*46bdb399SToby Isaac         PetscInt childId;
2676*46bdb399SToby Isaac 
2677*46bdb399SToby Isaac         childId = childIds[p-pStartF];
2678*46bdb399SToby Isaac         if (childId <= 0) { /* no child interpolation: one nnz per */
2679*46bdb399SToby Isaac           if (numFields) {
2680*46bdb399SToby Isaac             PetscInt f, count;
2681*46bdb399SToby Isaac             for (f = 0, count = 0; f < numFields; f++) {
2682*46bdb399SToby Isaac               PetscInt numRows = rowOffsets[f+1] - rowOffsets[f], row;
2683*46bdb399SToby Isaac               for (row = 0; row < numRows; row++) {
2684*46bdb399SToby Isaac                 PetscInt gIndCoarse = pInd[colOffsets[f] + row];
2685*46bdb399SToby Isaac                 PetscInt gIndFine   = rowIndices[rowOffsets[f] + row];
2686*46bdb399SToby Isaac                 if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */
2687*46bdb399SToby Isaac                   if (gIndFine < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs");
2688*46bdb399SToby Isaac                   dnnz[gOff + count++] = 1;
2689*46bdb399SToby Isaac                 }
2690*46bdb399SToby Isaac                 else if (gIndCoarse >= 0) { /* remote */
2691*46bdb399SToby Isaac                   if (gIndFine < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs");
2692*46bdb399SToby Isaac                   onnz[gOff + count++] = 1;
2693*46bdb399SToby Isaac                 }
2694*46bdb399SToby Isaac                 else { /* constrained */
2695*46bdb399SToby Isaac                   if (gIndFine >= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs");
2696*46bdb399SToby Isaac                 }
2697*46bdb399SToby Isaac               }
2698*46bdb399SToby Isaac             }
2699*46bdb399SToby Isaac           }
2700*46bdb399SToby Isaac           else {
2701*46bdb399SToby Isaac             PetscInt count, i;
2702*46bdb399SToby Isaac             for (i = 0, count = 0; i < gDof; i++) {
2703*46bdb399SToby Isaac               PetscInt gIndCoarse = pInd[i];
2704*46bdb399SToby Isaac               PetscInt gIndFine   = rowIndices[i];
2705*46bdb399SToby Isaac               if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */
2706*46bdb399SToby Isaac                 if (gIndFine < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs");
2707*46bdb399SToby Isaac                 dnnz[gOff + count++] = 1;
2708*46bdb399SToby Isaac               }
2709*46bdb399SToby Isaac               else if (gIndCoarse >= 0) { /* remote */
2710*46bdb399SToby Isaac                 if (gIndFine < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs");
2711*46bdb399SToby Isaac                 onnz[gOff + count++] = 1;
2712*46bdb399SToby Isaac               }
2713*46bdb399SToby Isaac               else { /* constrained */
2714*46bdb399SToby Isaac                 if (gIndFine >= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatched number of constrained dofs");
2715*46bdb399SToby Isaac               }
2716*46bdb399SToby Isaac             }
2717*46bdb399SToby Isaac           }
2718*46bdb399SToby Isaac         }
2719*46bdb399SToby Isaac         else { /* interpolate from all */
2720*46bdb399SToby Isaac           if (numFields) {
2721*46bdb399SToby Isaac             PetscInt f, count;
2722*46bdb399SToby Isaac             for (f = 0, count = 0; f < numFields; f++) {
2723*46bdb399SToby Isaac               PetscInt numRows = rowOffsets[f+1] - rowOffsets[f], row;
2724*46bdb399SToby Isaac               for (row = 0; row < numRows; row++) {
2725*46bdb399SToby Isaac                 PetscInt gIndFine = rowIndices[rowOffsets[f] + row];
2726*46bdb399SToby Isaac                 if (gIndFine >= 0) {
2727*46bdb399SToby Isaac                   dnnz[gOff + count] = fNumD[f];
2728*46bdb399SToby Isaac                   onnz[gOff + count++] = fNumO[f];
2729*46bdb399SToby Isaac                 }
2730*46bdb399SToby Isaac               }
2731*46bdb399SToby Isaac             }
2732*46bdb399SToby Isaac           }
2733*46bdb399SToby Isaac           else {
2734*46bdb399SToby Isaac             PetscInt count, i;
2735*46bdb399SToby Isaac             for (i = 0, count = 0; i < gDof; i++) {
2736*46bdb399SToby Isaac               PetscInt gIndFine = rowIndices[i];
2737*46bdb399SToby Isaac               if (gIndFine >= 0) {
2738*46bdb399SToby Isaac                 dnnz[gOff + count] = numD;
2739*46bdb399SToby Isaac                 onnz[gOff + count++] = numO;
2740*46bdb399SToby Isaac               }
2741*46bdb399SToby Isaac             }
2742*46bdb399SToby Isaac           }
2743*46bdb399SToby Isaac         }
2744*46bdb399SToby Isaac       }
2745*46bdb399SToby Isaac       else { /* interpolate from all */
2746*46bdb399SToby Isaac         if (numFields) {
2747*46bdb399SToby Isaac           PetscInt f, count;
2748*46bdb399SToby Isaac           for (f = 0, count = 0; f < numFields; f++) {
2749*46bdb399SToby Isaac             PetscInt numRows = rowOffsets[f+1] - rowOffsets[f], row;
2750*46bdb399SToby Isaac             for (row = 0; row < numRows; row++) {
2751*46bdb399SToby Isaac               PetscInt gIndFine = rowIndices[rowOffsets[f] + row];
2752*46bdb399SToby Isaac               if (gIndFine >= 0) {
2753*46bdb399SToby Isaac                 dnnz[gOff + count] = fNumD[f];
2754*46bdb399SToby Isaac                 onnz[gOff + count++] = fNumO[f];
2755*46bdb399SToby Isaac               }
2756*46bdb399SToby Isaac             }
2757*46bdb399SToby Isaac           }
2758*46bdb399SToby Isaac         }
2759*46bdb399SToby Isaac         else { /* every dof get a full row */
2760*46bdb399SToby Isaac           PetscInt count, i;
2761*46bdb399SToby Isaac           for (i = 0, count = 0; i < gDof; i++) {
2762*46bdb399SToby Isaac             PetscInt gIndFine = rowIndices[i];
2763*46bdb399SToby Isaac             if (gIndFine >= 0) {
2764*46bdb399SToby Isaac               dnnz[gOff + count] = numD;
2765*46bdb399SToby Isaac               onnz[gOff + count++] = numO;
2766*46bdb399SToby Isaac             }
2767*46bdb399SToby Isaac           }
2768*46bdb399SToby Isaac         }
2769*46bdb399SToby Isaac       }
2770*46bdb399SToby Isaac       ierr = DMRestoreWorkArray(fine,gDof,PETSC_INT,&rowIndices);CHKERRQ(ierr);
2771*46bdb399SToby Isaac     }
2772*46bdb399SToby Isaac     ierr = MatXAIJSetPreallocation(mat,1,dnnz,onnz,NULL,NULL);CHKERRQ(ierr);
2773*46bdb399SToby Isaac     ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
2774*46bdb399SToby Isaac   }
27756ecaa68aSToby Isaac   ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);
27766ecaa68aSToby Isaac   PetscFunctionReturn(0);
27776ecaa68aSToby Isaac }
2778