xref: /petsc/src/dm/impls/plex/plexrefine.c (revision dae4404a8f1479c6635a6fb5f4da602f46bf575b)
175d3a19aSMatthew G. Knepley #include <petsc-private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
275d3a19aSMatthew G. Knepley #include <petscsf.h>
375d3a19aSMatthew G. Knepley 
475d3a19aSMatthew G. Knepley #undef __FUNCT__
575d3a19aSMatthew G. Knepley #define __FUNCT__ "GetDepthStart_Private"
675d3a19aSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart)
775d3a19aSMatthew G. Knepley {
875d3a19aSMatthew G. Knepley   PetscFunctionBegin;
975d3a19aSMatthew G. Knepley   if (cStart) *cStart = 0;
1075d3a19aSMatthew G. Knepley   if (vStart) *vStart = depthSize[depth];
1175d3a19aSMatthew G. Knepley   if (fStart) *fStart = depthSize[depth] + depthSize[0];
1275d3a19aSMatthew G. Knepley   if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1];
1375d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
1475d3a19aSMatthew G. Knepley }
1575d3a19aSMatthew G. Knepley 
1675d3a19aSMatthew G. Knepley #undef __FUNCT__
1775d3a19aSMatthew G. Knepley #define __FUNCT__ "GetDepthEnd_Private"
1875d3a19aSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd)
1975d3a19aSMatthew G. Knepley {
2075d3a19aSMatthew G. Knepley   PetscFunctionBegin;
2175d3a19aSMatthew G. Knepley   if (cEnd) *cEnd = depthSize[depth];
2275d3a19aSMatthew G. Knepley   if (vEnd) *vEnd = depthSize[depth] + depthSize[0];
2375d3a19aSMatthew G. Knepley   if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1];
2475d3a19aSMatthew G. Knepley   if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1];
2575d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
2675d3a19aSMatthew G. Knepley }
2775d3a19aSMatthew G. Knepley 
2875d3a19aSMatthew G. Knepley #undef __FUNCT__
29b5da9499SMatthew G. Knepley #define __FUNCT__ "DMPlexGetNumHybridFaces_Internal"
30b5da9499SMatthew G. Knepley /* This is a stopgap since we do not currently keep track of faces for hybrid cells */
31b5da9499SMatthew G. Knepley static PetscErrorCode DMPlexGetNumHybridFaces_Internal(DM dm, PetscInt *numHybridFaces)
32b5da9499SMatthew G. Knepley {
33b5da9499SMatthew G. Knepley   PetscInt       eStart, eEnd, eMax, cEnd, cMax, c, hEdges = 0;
34b5da9499SMatthew G. Knepley   PetscErrorCode ierr;
35b5da9499SMatthew G. Knepley 
36b5da9499SMatthew G. Knepley   PetscFunctionBegin;
37b5da9499SMatthew G. Knepley   *numHybridFaces = 0;
38b5da9499SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
39b5da9499SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);CHKERRQ(ierr);
40b5da9499SMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, &eMax, NULL);CHKERRQ(ierr);
41b5da9499SMatthew G. Knepley   if (cMax < 0) PetscFunctionReturn(0);
42b5da9499SMatthew G. Knepley   /* Count interior edges in hybrid cells */
43b5da9499SMatthew G. Knepley   for (c = cMax; c < cEnd; ++c) {
44b5da9499SMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl;
45b5da9499SMatthew G. Knepley 
46b5da9499SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
47b5da9499SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
48b5da9499SMatthew G. Knepley       const PetscInt p = closure[cl];
49b5da9499SMatthew G. Knepley 
50b5da9499SMatthew G. Knepley       if ((p >= eStart) && (p < eMax)) ++hEdges;
51b5da9499SMatthew G. Knepley     }
52b5da9499SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
53b5da9499SMatthew G. Knepley   }
54b5da9499SMatthew G. Knepley   if (hEdges%2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of interior edges in hybrid cells cannot be odd: %d", hEdges);
55b5da9499SMatthew G. Knepley   *numHybridFaces = hEdges/2;
56b5da9499SMatthew G. Knepley   PetscFunctionReturn(0);
57b5da9499SMatthew G. Knepley }
58b5da9499SMatthew G. Knepley 
59b5da9499SMatthew G. Knepley #undef __FUNCT__
6075d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerGetSizes"
6175d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[])
6275d3a19aSMatthew G. Knepley {
63b5da9499SMatthew G. Knepley   PetscInt       numHybridFaces, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax;
6475d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
6575d3a19aSMatthew G. Knepley 
6675d3a19aSMatthew G. Knepley   PetscFunctionBegin;
6775d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
6875d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
6975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
7075d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
7175d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
7275d3a19aSMatthew G. Knepley   switch (refiner) {
7375d3a19aSMatthew G. Knepley   case 1:
7475d3a19aSMatthew G. Knepley     /* Simplicial 2D */
7575d3a19aSMatthew G. Knepley     depthSize[0] = vEnd - vStart + fEnd - fStart;         /* Add a vertex on every face */
7675d3a19aSMatthew G. Knepley     depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */
7775d3a19aSMatthew G. Knepley     depthSize[2] = 4*(cEnd - cStart);                     /* Every cell split into 4 cells */
7875d3a19aSMatthew G. Knepley     break;
7975d3a19aSMatthew G. Knepley   case 3:
80d963de37SMatthew G. Knepley     /* Hybrid Simplicial 2D */
8175d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
8275d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
8375d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
8475d3a19aSMatthew G. Knepley     fMax         = PetscMin(fEnd, fMax);
8575d3a19aSMatthew G. Knepley     depthSize[0] = vEnd - vStart + fMax - fStart;                                         /* Add a vertex on every face, but not hybrid faces */
8675d3a19aSMatthew G. Knepley     depthSize[1] = 2*(fMax - fStart) + 3*(cMax - cStart) + (fEnd - fMax) + (cEnd - cMax); /* Every interior face is split into 2 faces, 3 faces are added for each interior cell, and one in each hybrid cell */
8775d3a19aSMatthew G. Knepley     depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax);                                   /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */
8875d3a19aSMatthew G. Knepley     break;
8975d3a19aSMatthew G. Knepley   case 2:
9075d3a19aSMatthew G. Knepley     /* Hex 2D */
9175d3a19aSMatthew G. Knepley     depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */
9275d3a19aSMatthew G. Knepley     depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart);         /* Every face is split into 2 faces and 4 faces are added for each cell */
9375d3a19aSMatthew G. Knepley     depthSize[2] = 4*(cEnd - cStart);                             /* Every cell split into 4 cells */
9475d3a19aSMatthew G. Knepley     break;
95b5da9499SMatthew G. Knepley   case 5:
96b5da9499SMatthew G. Knepley     /* Simplicial 3D */
97b5da9499SMatthew G. Knepley     depthSize[0] =    vEnd - vStart  +    eEnd - eStart;                    /* Add a vertex on every edge */
98b5da9499SMatthew G. Knepley     depthSize[1] = 2*(eEnd - eStart) + 3*(fEnd - fStart) + (cEnd - cStart); /* Every edge is split into 2 edges, 3 edges are added for each face, and 1 edge for each cell */
99b5da9499SMatthew G. Knepley     depthSize[2] = 4*(fEnd - fStart) + 8*(cEnd - cStart);                   /* Every face split into 4 faces and 8 faces are added for each cell */
100b5da9499SMatthew G. Knepley     depthSize[3] = 8*(cEnd - cStart);                                       /* Every cell split into 8 cells */
101b5da9499SMatthew G. Knepley     break;
1022eabf88fSMatthew G. Knepley   case 6:
1032eabf88fSMatthew G. Knepley     /* Hex 3D */
1042eabf88fSMatthew G. Knepley     depthSize[0] = vEnd - vStart + eEnd - eStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every edge, face and cell */
1052eabf88fSMatthew G. Knepley     depthSize[1] = 2*(eEnd - eStart) +  4*(fEnd - fStart) + 6*(cEnd - cStart);    /* Every edge is split into 2 edge, 4 edges are added for each face, and 6 edges for each cell */
1062eabf88fSMatthew G. Knepley     depthSize[2] = 4*(fEnd - fStart) + 12*(cEnd - cStart);                        /* Every face is split into 4 faces, and 12 faces are added for each cell */
1072eabf88fSMatthew G. Knepley     depthSize[3] = 8*(cEnd - cStart);                                             /* Every cell split into 8 cells */
1082eabf88fSMatthew G. Knepley     break;
109b5da9499SMatthew G. Knepley   case 7:
110b5da9499SMatthew G. Knepley     /* Hybrid Simplicial 3D */
111b5da9499SMatthew G. Knepley     ierr = DMPlexGetNumHybridFaces_Internal(dm, &numHybridFaces);CHKERRQ(ierr);
112b5da9499SMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
113b5da9499SMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
114b5da9499SMatthew G. Knepley     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
115b5da9499SMatthew G. Knepley     eMax = PetscMin(eEnd, eMax);
116*dae4404aSMatthew G. Knepley     /* Tetrahedra */
117*dae4404aSMatthew G. Knepley     depthSize[0]  =    vEnd - vStart  +    eMax - eStart;                    /* Add a vertex on every interior edge */
118*dae4404aSMatthew G. Knepley     depthSize[1]  = 2*(eMax - eStart) + 3*(fMax - fStart) + (cMax - cStart); /* Every interior edge split into 2 edges, 3 edges added for each interior face, 1 edge for each interior cell */
119*dae4404aSMatthew G. Knepley     depthSize[2]  = 4*(fMax - fStart) + 8*(cMax - cStart);                   /* Every interior face split into 4 faces, 8 faces added for each interior cell */
120*dae4404aSMatthew G. Knepley     depthSize[3]  = 8*(cMax - cStart);                                       /* Every interior cell split into 8 cells */
121*dae4404aSMatthew G. Knepley     /* Triangular Prisms */
122*dae4404aSMatthew G. Knepley     depthSize[0] += 0;                                                       /* No hybrid vertices */
123*dae4404aSMatthew G. Knepley     depthSize[1] +=   (eEnd - eMax)   +   (fEnd - fMax);                     /* Every hybrid edge remains, 1 edge for every hybrid face */
124*dae4404aSMatthew G. Knepley     depthSize[2] += 4*(fEnd - fMax)   + 3*(cEnd - cMax);                     /* Every hybrid face split into 2 faces and 3 faces are added for each hybrid cell */
125*dae4404aSMatthew G. Knepley     depthSize[3] += 4*(cEnd - cMax);                                         /* Every hybrid cell split into 4 cells */
126b5da9499SMatthew G. Knepley     break;
12775d3a19aSMatthew G. Knepley   default:
12875d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
12975d3a19aSMatthew G. Knepley   }
13075d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
13175d3a19aSMatthew G. Knepley }
13275d3a19aSMatthew G. Knepley 
13342525629SMatthew G. Knepley /* Return triangle edge for orientation o, if it is r for o == 0 */
13442525629SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetTriEdge_Static(PetscInt o, PetscInt r) {
135518a8359SMatthew G. Knepley   return (o < 0 ? 2-(o+r) : o+r)%3;
136518a8359SMatthew G. Knepley }
137518a8359SMatthew G. Knepley 
138518a8359SMatthew G. Knepley /* Return triangle subface for orientation o, if it is r for o == 0 */
139518a8359SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetTriSubface_Static(PetscInt o, PetscInt r) {
140518a8359SMatthew G. Knepley   return (o < 0 ? 0-(o+r) : o+r)%3;
14142525629SMatthew G. Knepley }
14242525629SMatthew G. Knepley 
143e3f8b1d6SMatthew G. Knepley /* Return quad edge for orientation o, if it is r for o == 0 */
144e3f8b1d6SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetQuadEdge_Static(PetscInt o, PetscInt r) {
145e3f8b1d6SMatthew G. Knepley   return (o < 0 ? 3-(o+r) : o+r)%4;
146e3f8b1d6SMatthew G. Knepley }
147e3f8b1d6SMatthew G. Knepley 
148e3f8b1d6SMatthew G. Knepley /* Return quad subface for orientation o, if it is r for o == 0 */
149e3f8b1d6SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetQuadSubface_Static(PetscInt o, PetscInt r) {
150e3f8b1d6SMatthew G. Knepley   return (o < 0 ? 0-(o+r) : o+r)%4;
15142525629SMatthew G. Knepley }
15242525629SMatthew G. Knepley 
15375d3a19aSMatthew G. Knepley #undef __FUNCT__
15475d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetConeSizes"
15575d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
15675d3a19aSMatthew G. Knepley {
157b5da9499SMatthew G. Knepley   PetscInt       depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, e, r;
15875d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
15975d3a19aSMatthew G. Knepley 
16075d3a19aSMatthew G. Knepley   PetscFunctionBegin;
16175d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
16275d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
16375d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
16475d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
16575d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
16675d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
16775d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
16875d3a19aSMatthew G. Knepley   switch (refiner) {
16975d3a19aSMatthew G. Knepley   case 1:
17075d3a19aSMatthew G. Knepley     /* Simplicial 2D */
17175d3a19aSMatthew G. Knepley     /* All cells have 3 faces */
17275d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
17375d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
17475d3a19aSMatthew G. Knepley         const PetscInt newp = (c - cStart)*4 + r;
17575d3a19aSMatthew G. Knepley 
17675d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
17775d3a19aSMatthew G. Knepley       }
17875d3a19aSMatthew G. Knepley     }
17975d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
18075d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
18175d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
18275d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
18375d3a19aSMatthew G. Knepley         PetscInt       size;
18475d3a19aSMatthew G. Knepley 
18575d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
18675d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
18775d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
18875d3a19aSMatthew G. Knepley       }
18975d3a19aSMatthew G. Knepley     }
19075d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
19175d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
19275d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
19375d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
19475d3a19aSMatthew G. Knepley 
19575d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
19675d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
19775d3a19aSMatthew G. Knepley       }
19875d3a19aSMatthew G. Knepley     }
19975d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
20075d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
20175d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
20275d3a19aSMatthew G. Knepley       PetscInt       size;
20375d3a19aSMatthew G. Knepley 
20475d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
20575d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
20675d3a19aSMatthew G. Knepley     }
20775d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells*2 supports */
20875d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
20975d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
21075d3a19aSMatthew G. Knepley       PetscInt       size;
21175d3a19aSMatthew G. Knepley 
21275d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
21375d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr);
21475d3a19aSMatthew G. Knepley     }
21575d3a19aSMatthew G. Knepley     break;
21675d3a19aSMatthew G. Knepley   case 2:
21775d3a19aSMatthew G. Knepley     /* Hex 2D */
21875d3a19aSMatthew G. Knepley     /* All cells have 4 faces */
21975d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
22075d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
22175d3a19aSMatthew G. Knepley         const PetscInt newp = (c - cStart)*4 + r;
22275d3a19aSMatthew G. Knepley 
22375d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
22475d3a19aSMatthew G. Knepley       }
22575d3a19aSMatthew G. Knepley     }
22675d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
22775d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
22875d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
22975d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
23075d3a19aSMatthew G. Knepley         PetscInt       size;
23175d3a19aSMatthew G. Knepley 
23275d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
23375d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
23475d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
23575d3a19aSMatthew G. Knepley       }
23675d3a19aSMatthew G. Knepley     }
23775d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
23875d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
23975d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
24075d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
24175d3a19aSMatthew G. Knepley 
24275d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
24375d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
24475d3a19aSMatthew G. Knepley       }
24575d3a19aSMatthew G. Knepley     }
24675d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
24775d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
24875d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
24975d3a19aSMatthew G. Knepley       PetscInt       size;
25075d3a19aSMatthew G. Knepley 
25175d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
25275d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
25375d3a19aSMatthew G. Knepley     }
25475d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells supports */
25575d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
25675d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
25775d3a19aSMatthew G. Knepley       PetscInt       size;
25875d3a19aSMatthew G. Knepley 
25975d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
26075d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
26175d3a19aSMatthew G. Knepley     }
26275d3a19aSMatthew G. Knepley     /* Cell vertices have 4 supports */
26375d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
26475d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
26575d3a19aSMatthew G. Knepley 
26675d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
26775d3a19aSMatthew G. Knepley     }
26875d3a19aSMatthew G. Knepley     break;
26975d3a19aSMatthew G. Knepley   case 3:
270d963de37SMatthew G. Knepley     /* Hybrid Simplicial 2D */
27175d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
27275d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
27375d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
27475d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
27575d3a19aSMatthew G. Knepley     ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
27675d3a19aSMatthew G. Knepley     /* Interior cells have 3 faces */
27775d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
27875d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
27975d3a19aSMatthew G. Knepley         const PetscInt newp = cStartNew + (c - cStart)*4 + r;
28075d3a19aSMatthew G. Knepley 
28175d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
28275d3a19aSMatthew G. Knepley       }
28375d3a19aSMatthew G. Knepley     }
28475d3a19aSMatthew G. Knepley     /* Hybrid cells have 4 faces */
28575d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
28675d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
28775d3a19aSMatthew G. Knepley         const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
28875d3a19aSMatthew G. Knepley 
28975d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
29075d3a19aSMatthew G. Knepley       }
29175d3a19aSMatthew G. Knepley     }
29275d3a19aSMatthew G. Knepley     /* Interior split faces have 2 vertices and the same cells as the parent */
29375d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
29475d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
29575d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
29675d3a19aSMatthew G. Knepley         PetscInt       size;
29775d3a19aSMatthew G. Knepley 
29875d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
29975d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
30075d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
30175d3a19aSMatthew G. Knepley       }
30275d3a19aSMatthew G. Knepley     }
30375d3a19aSMatthew G. Knepley     /* Interior cell faces have 2 vertices and 2 cells */
30475d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
30575d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
30675d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
30775d3a19aSMatthew G. Knepley 
30875d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
30975d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
31075d3a19aSMatthew G. Knepley       }
31175d3a19aSMatthew G. Knepley     }
31275d3a19aSMatthew G. Knepley     /* Hybrid faces have 2 vertices and the same cells */
31375d3a19aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
31475d3a19aSMatthew G. Knepley       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
31575d3a19aSMatthew G. Knepley       PetscInt       size;
31675d3a19aSMatthew G. Knepley 
31775d3a19aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
31875d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
31975d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
32075d3a19aSMatthew G. Knepley     }
32175d3a19aSMatthew G. Knepley     /* Hybrid cell faces have 2 vertices and 2 cells */
32275d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
32375d3a19aSMatthew G. Knepley       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
32475d3a19aSMatthew G. Knepley 
32575d3a19aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
32675d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
32775d3a19aSMatthew G. Knepley     }
32875d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
32975d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
33075d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
33175d3a19aSMatthew G. Knepley       PetscInt       size;
33275d3a19aSMatthew G. Knepley 
33375d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
33475d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
33575d3a19aSMatthew G. Knepley     }
33675d3a19aSMatthew G. Knepley     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
33775d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
33875d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
33975d3a19aSMatthew G. Knepley       const PetscInt *support;
34075d3a19aSMatthew G. Knepley       PetscInt       size, newSize = 2, s;
34175d3a19aSMatthew G. Knepley 
34275d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
34375d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
34475d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
34575d3a19aSMatthew G. Knepley         if (support[s] >= cMax) newSize += 1;
34675d3a19aSMatthew G. Knepley         else newSize += 2;
34775d3a19aSMatthew G. Knepley       }
34875d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr);
34975d3a19aSMatthew G. Knepley     }
35075d3a19aSMatthew G. Knepley     break;
351b5da9499SMatthew G. Knepley   case 5:
352b5da9499SMatthew G. Knepley     /* Simplicial 3D */
353b5da9499SMatthew G. Knepley     /* All cells have 4 faces */
354b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
355b5da9499SMatthew G. Knepley       for (r = 0; r < 8; ++r) {
356*dae4404aSMatthew G. Knepley         const PetscInt newp = cStartNew + (c - cStart)*8 + r;
357b5da9499SMatthew G. Knepley 
358b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
359b5da9499SMatthew G. Knepley       }
360b5da9499SMatthew G. Knepley     }
361b5da9499SMatthew G. Knepley     /* Split faces have 3 edges and the same cells as the parent */
362b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
363b5da9499SMatthew G. Knepley       for (r = 0; r < 4; ++r) {
364b5da9499SMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
365b5da9499SMatthew G. Knepley         PetscInt       size;
366b5da9499SMatthew G. Knepley 
367b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
368b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
369b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
370b5da9499SMatthew G. Knepley       }
371b5da9499SMatthew G. Knepley     }
372b5da9499SMatthew G. Knepley     /* Interior faces have 3 edges and 2 cells */
373b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
374b5da9499SMatthew G. Knepley       for (r = 0; r < 8; ++r) {
375b5da9499SMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + r;
376b5da9499SMatthew G. Knepley 
377b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
378b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
379b5da9499SMatthew G. Knepley       }
380b5da9499SMatthew G. Knepley     }
381b5da9499SMatthew G. Knepley     /* Split edges have 2 vertices and the same faces */
382b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
383b5da9499SMatthew G. Knepley       for (r = 0; r < 2; ++r) {
384b5da9499SMatthew G. Knepley         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
385b5da9499SMatthew G. Knepley         PetscInt       size;
386b5da9499SMatthew G. Knepley 
387b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
388b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
389b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
390b5da9499SMatthew G. Knepley       }
391b5da9499SMatthew G. Knepley     }
392b5da9499SMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
393b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
394b5da9499SMatthew G. Knepley       for (r = 0; r < 3; ++r) {
395b5da9499SMatthew G. Knepley         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
396b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
397b5da9499SMatthew G. Knepley         PetscInt        coneSize, c, supportSize, s, er, intFaces = 0;
398b5da9499SMatthew G. Knepley 
399b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
400b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
401b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
402b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
403b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
404b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
405b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
406b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
40786f0afeeSMatthew G. Knepley           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
40886f0afeeSMatthew G. Knepley           er = ornt[c] < 0 ? (-(ornt[c]+1) + 2-r)%3 : (ornt[c] + r)%3;
409b5da9499SMatthew G. Knepley           if (er == eint[c]) {
410b5da9499SMatthew G. Knepley             intFaces += 1;
411b5da9499SMatthew G. Knepley           } else {
412b5da9499SMatthew G. Knepley             intFaces += 2;
413b5da9499SMatthew G. Knepley           }
414b5da9499SMatthew G. Knepley         }
415b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2+intFaces);CHKERRQ(ierr);
416b5da9499SMatthew G. Knepley       }
417b5da9499SMatthew G. Knepley     }
418b5da9499SMatthew G. Knepley     /* Interior edges have 2 vertices and 4 faces */
419b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
420b5da9499SMatthew G. Knepley       const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
421b5da9499SMatthew G. Knepley 
422b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
423b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
424b5da9499SMatthew G. Knepley     }
425b5da9499SMatthew G. Knepley     /* Old vertices have identical supports */
426b5da9499SMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
427b5da9499SMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
428b5da9499SMatthew G. Knepley       PetscInt       size;
429b5da9499SMatthew G. Knepley 
430b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
431b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
432b5da9499SMatthew G. Knepley     }
433b5da9499SMatthew G. Knepley     /* Edge vertices have 2 + faces*2 + cells*0/1 supports */
434b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
435b5da9499SMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
436b5da9499SMatthew G. Knepley       PetscInt       size, *star = NULL, starSize, s, cellSize = 0;
437b5da9499SMatthew G. Knepley 
438b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
439b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
440b5da9499SMatthew G. Knepley       for (s = 0; s < starSize*2; s += 2) {
441b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt;
442b5da9499SMatthew G. Knepley         PetscInt        e01, e23;
443b5da9499SMatthew G. Knepley 
444b5da9499SMatthew G. Knepley         if ((star[s] >= cStart) && (star[s] < cEnd)) {
445b5da9499SMatthew G. Knepley           /* Check edge 0-1 */
446b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
447b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
448b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
44942525629SMatthew G. Knepley           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
450b5da9499SMatthew G. Knepley           /* Check edge 2-3 */
451b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
452b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
45342525629SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
45442525629SMatthew G. Knepley           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
455b5da9499SMatthew G. Knepley           if ((e01 == e) || (e23 == e)) ++cellSize;
456b5da9499SMatthew G. Knepley         }
457b5da9499SMatthew G. Knepley       }
458b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
459b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2 + cellSize);CHKERRQ(ierr);
460b5da9499SMatthew G. Knepley     }
461b5da9499SMatthew G. Knepley     break;
462*dae4404aSMatthew G. Knepley   case 7:
463*dae4404aSMatthew G. Knepley     /* Hybrid Simplicial 2D */
464*dae4404aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
465*dae4404aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
466*dae4404aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
467*dae4404aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
468*dae4404aSMatthew G. Knepley     ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax-cStart)*8, PETSC_DETERMINE, eStartNew + (eMax-eStart)*2 + (cMax-cStart)*13, PETSC_DETERMINE);CHKERRQ(ierr);
469*dae4404aSMatthew G. Knepley     /* Interior cells have 4 faces */
470*dae4404aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
471*dae4404aSMatthew G. Knepley       for (r = 0; r < 8; ++r) {
472*dae4404aSMatthew G. Knepley         const PetscInt newp = cStartNew + (c - cStart)*8 + r;
473*dae4404aSMatthew G. Knepley 
474*dae4404aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
475*dae4404aSMatthew G. Knepley       }
476*dae4404aSMatthew G. Knepley     }
477*dae4404aSMatthew G. Knepley     /* Hybrid cells have 5 faces */
478*dae4404aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
479*dae4404aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
480*dae4404aSMatthew G. Knepley         const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;
481*dae4404aSMatthew G. Knepley 
482*dae4404aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 5);CHKERRQ(ierr);
483*dae4404aSMatthew G. Knepley       }
484*dae4404aSMatthew G. Knepley     }
485*dae4404aSMatthew G. Knepley     /* Interior/Hybrid split faces have 3 edges and the same cells as the parent */
486*dae4404aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
487*dae4404aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
488*dae4404aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
489*dae4404aSMatthew G. Knepley         PetscInt       size;
490*dae4404aSMatthew G. Knepley 
491*dae4404aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
492*dae4404aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
493*dae4404aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
494*dae4404aSMatthew G. Knepley       }
495*dae4404aSMatthew G. Knepley     }
496*dae4404aSMatthew G. Knepley     /* Interior cell faces have 3 edges and 2 cells */
497*dae4404aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
498*dae4404aSMatthew G. Knepley       for (r = 0; r < 8; ++r) {
499*dae4404aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + r;
500*dae4404aSMatthew G. Knepley 
501*dae4404aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
502*dae4404aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
503*dae4404aSMatthew G. Knepley       }
504*dae4404aSMatthew G. Knepley     }
505*dae4404aSMatthew G. Knepley     /* Split edges have 2 vertices and the same faces */
506*dae4404aSMatthew G. Knepley     for (e = eStart; e < eMax; ++e) {
507*dae4404aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
508*dae4404aSMatthew G. Knepley         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
509*dae4404aSMatthew G. Knepley         PetscInt       size;
510*dae4404aSMatthew G. Knepley 
511*dae4404aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
512*dae4404aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
513*dae4404aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
514*dae4404aSMatthew G. Knepley       }
515*dae4404aSMatthew G. Knepley     }
516*dae4404aSMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
517*dae4404aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
518*dae4404aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
519*dae4404aSMatthew G. Knepley         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
520*dae4404aSMatthew G. Knepley         const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
521*dae4404aSMatthew G. Knepley         PetscInt        coneSize, c, supportSize, s, er, intFaces = 0;
522*dae4404aSMatthew G. Knepley 
523*dae4404aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
524*dae4404aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
525*dae4404aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
526*dae4404aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
527*dae4404aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
528*dae4404aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
529*dae4404aSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
530*dae4404aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
531*dae4404aSMatthew G. Knepley           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
532*dae4404aSMatthew G. Knepley           er = ornt[c] < 0 ? (-(ornt[c]+1) + 2-r)%3 : (ornt[c] + r)%3;
533*dae4404aSMatthew G. Knepley           if (er == eint[c]) {
534*dae4404aSMatthew G. Knepley             intFaces += 1;
535*dae4404aSMatthew G. Knepley           } else {
536*dae4404aSMatthew G. Knepley             intFaces += 2;
537*dae4404aSMatthew G. Knepley           }
538*dae4404aSMatthew G. Knepley         }
539*dae4404aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2+intFaces);CHKERRQ(ierr);
540*dae4404aSMatthew G. Knepley       }
541*dae4404aSMatthew G. Knepley     }
542*dae4404aSMatthew G. Knepley     /* Interior edges have 2 vertices and 4 faces */
543*dae4404aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
544*dae4404aSMatthew G. Knepley       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
545*dae4404aSMatthew G. Knepley 
546*dae4404aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
547*dae4404aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
548*dae4404aSMatthew G. Knepley     }
549*dae4404aSMatthew G. Knepley     /* Hybrid edges have 2 vertices and the same cells */
550*dae4404aSMatthew G. Knepley     for (e = eMax; e < eEnd; ++e) {
551*dae4404aSMatthew G. Knepley       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eEnd);
552*dae4404aSMatthew G. Knepley       PetscInt       size;
553*dae4404aSMatthew G. Knepley 
554*dae4404aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
555*dae4404aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
556*dae4404aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
557*dae4404aSMatthew G. Knepley     }
558*dae4404aSMatthew G. Knepley     /* Hybrid split edges have 2 vertices and 2 faces */
559*dae4404aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
560*dae4404aSMatthew G. Knepley       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
561*dae4404aSMatthew G. Knepley 
562*dae4404aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
563*dae4404aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
564*dae4404aSMatthew G. Knepley     }
565*dae4404aSMatthew G. Knepley     /* Old vertices have identical supports */
566*dae4404aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
567*dae4404aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
568*dae4404aSMatthew G. Knepley       PetscInt       size;
569*dae4404aSMatthew G. Knepley 
570*dae4404aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
571*dae4404aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
572*dae4404aSMatthew G. Knepley     }
573*dae4404aSMatthew G. Knepley     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
574*dae4404aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
575*dae4404aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
576*dae4404aSMatthew G. Knepley       const PetscInt *support;
577*dae4404aSMatthew G. Knepley       PetscInt       size, newSize = 2, s;
578*dae4404aSMatthew G. Knepley 
579*dae4404aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
580*dae4404aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
581*dae4404aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
582*dae4404aSMatthew G. Knepley         if (support[s] >= cMax) newSize += 1;
583*dae4404aSMatthew G. Knepley         else newSize += 2;
584*dae4404aSMatthew G. Knepley       }
585*dae4404aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr);
586*dae4404aSMatthew G. Knepley     }
587*dae4404aSMatthew G. Knepley     break;
5882eabf88fSMatthew G. Knepley   case 6:
5892eabf88fSMatthew G. Knepley     /* Hex 3D */
5902eabf88fSMatthew G. Knepley     /* All cells have 6 faces */
5912eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
5922eabf88fSMatthew G. Knepley       for (r = 0; r < 8; ++r) {
5932eabf88fSMatthew G. Knepley         const PetscInt newp = (c - cStart)*8 + r;
5942eabf88fSMatthew G. Knepley 
5952eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 6);CHKERRQ(ierr);
5962eabf88fSMatthew G. Knepley       }
5972eabf88fSMatthew G. Knepley     }
5982eabf88fSMatthew G. Knepley     /* Split faces have 4 edges and the same cells as the parent */
5992eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
6002eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
6012eabf88fSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
6022eabf88fSMatthew G. Knepley         PetscInt       size;
6032eabf88fSMatthew G. Knepley 
6042eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
6052eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
6062eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
6072eabf88fSMatthew G. Knepley       }
6082eabf88fSMatthew G. Knepley     }
6092eabf88fSMatthew G. Knepley     /* Interior faces have 4 edges and 2 cells */
6102eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
6112eabf88fSMatthew G. Knepley       for (r = 0; r < 12; ++r) {
6122eabf88fSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
6132eabf88fSMatthew G. Knepley 
6142eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
6152eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
6162eabf88fSMatthew G. Knepley       }
6172eabf88fSMatthew G. Knepley     }
6182eabf88fSMatthew G. Knepley     /* Split edges have 2 vertices and the same faces as the parent */
6192eabf88fSMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
6202eabf88fSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
6212eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
6222eabf88fSMatthew G. Knepley         PetscInt       size;
6232eabf88fSMatthew G. Knepley 
6242eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
6252eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
6262eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
6272eabf88fSMatthew G. Knepley       }
6282eabf88fSMatthew G. Knepley     }
6292eabf88fSMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells faces */
6302eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
6312eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
6322eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
6332eabf88fSMatthew G. Knepley         PetscInt       size;
6342eabf88fSMatthew G. Knepley 
6352eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
6362eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
6372eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2+size);CHKERRQ(ierr);
6382eabf88fSMatthew G. Knepley       }
6392eabf88fSMatthew G. Knepley     }
6402eabf88fSMatthew G. Knepley     /* Cell edges have 2 vertices and 4 faces */
6412eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
6422eabf88fSMatthew G. Knepley       for (r = 0; r < 6; ++r) {
6432eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
6442eabf88fSMatthew G. Knepley 
6452eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
6462eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
6472eabf88fSMatthew G. Knepley       }
6482eabf88fSMatthew G. Knepley     }
6492eabf88fSMatthew G. Knepley     /* Old vertices have identical supports */
6502eabf88fSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
6512eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
6522eabf88fSMatthew G. Knepley       PetscInt       size;
6532eabf88fSMatthew G. Knepley 
6542eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
6552eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
6562eabf88fSMatthew G. Knepley     }
6572eabf88fSMatthew G. Knepley     /* Edge vertices have 2 + faces supports */
6582eabf88fSMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
6592eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
6602eabf88fSMatthew G. Knepley       PetscInt       size;
6612eabf88fSMatthew G. Knepley 
6622eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
6632eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
6642eabf88fSMatthew G. Knepley     }
6652eabf88fSMatthew G. Knepley     /* Face vertices have 4 + cells supports */
6662eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
6672eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
6682eabf88fSMatthew G. Knepley       PetscInt       size;
6692eabf88fSMatthew G. Knepley 
6702eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
6712eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4 + size);CHKERRQ(ierr);
6722eabf88fSMatthew G. Knepley     }
6732eabf88fSMatthew G. Knepley     /* Cell vertices have 6 supports */
6742eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
6752eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
6762eabf88fSMatthew G. Knepley 
6772eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 6);CHKERRQ(ierr);
6782eabf88fSMatthew G. Knepley     }
6792eabf88fSMatthew G. Knepley     break;
68075d3a19aSMatthew G. Knepley   default:
68175d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
68275d3a19aSMatthew G. Knepley   }
68375d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
68475d3a19aSMatthew G. Knepley }
68575d3a19aSMatthew G. Knepley 
68675d3a19aSMatthew G. Knepley #undef __FUNCT__
68775d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetCones"
68875d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
68975d3a19aSMatthew G. Knepley {
690b5da9499SMatthew G. Knepley   const PetscInt *faces, cellInd[4] = {0, 1, 2, 3};
691b5da9499SMatthew G. Knepley   PetscInt        depth, cStart, cEnd, cMax, cStartNew, cEndNew, c, vStart, vEnd, vMax, vStartNew, vEndNew, v, fStart, fEnd, fMax, fStartNew, fEndNew, f, eStart, eEnd, eMax, eStartNew, eEndNew, e, r, p;
69275d3a19aSMatthew G. Knepley   PetscInt        maxSupportSize, *supportRef;
69375d3a19aSMatthew G. Knepley   PetscErrorCode  ierr;
69475d3a19aSMatthew G. Knepley 
69575d3a19aSMatthew G. Knepley   PetscFunctionBegin;
69675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
69775d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
69875d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
69975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
70075d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
70175d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
70275d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
70375d3a19aSMatthew G. Knepley   ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr);
70475d3a19aSMatthew G. Knepley   switch (refiner) {
70575d3a19aSMatthew G. Knepley   case 1:
70675d3a19aSMatthew G. Knepley     /* Simplicial 2D */
70775d3a19aSMatthew G. Knepley     /*
70875d3a19aSMatthew G. Knepley      2
70975d3a19aSMatthew G. Knepley      |\
71075d3a19aSMatthew G. Knepley      | \
71175d3a19aSMatthew G. Knepley      |  \
71275d3a19aSMatthew G. Knepley      |   \
71375d3a19aSMatthew G. Knepley      | C  \
71475d3a19aSMatthew G. Knepley      |     \
71575d3a19aSMatthew G. Knepley      |      \
71675d3a19aSMatthew G. Knepley      2---1---1
71775d3a19aSMatthew G. Knepley      |\  D  / \
71875d3a19aSMatthew G. Knepley      | 2   0   \
71975d3a19aSMatthew G. Knepley      |A \ /  B  \
72075d3a19aSMatthew G. Knepley      0---0-------1
72175d3a19aSMatthew G. Knepley      */
72275d3a19aSMatthew G. Knepley     /* All cells have 3 faces */
72375d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
72475d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*4;
72575d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
72675d3a19aSMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
72775d3a19aSMatthew G. Knepley 
72875d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
72975d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
73075d3a19aSMatthew G. Knepley       /* A triangle */
73175d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
73275d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
73375d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
73475d3a19aSMatthew G. Knepley       orntNew[1] = -2;
73575d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
73675d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
73775d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
73875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
73975d3a19aSMatthew G. Knepley #if 1
74075d3a19aSMatthew G. Knepley       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
74175d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
74275d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
74375d3a19aSMatthew G. Knepley       }
74475d3a19aSMatthew G. Knepley #endif
74575d3a19aSMatthew G. Knepley       /* B triangle */
74675d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
74775d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
74875d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
74975d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
75075d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
75175d3a19aSMatthew G. Knepley       orntNew[2] = -2;
75275d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
75375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
75475d3a19aSMatthew G. Knepley #if 1
75575d3a19aSMatthew G. Knepley       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
75675d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
75775d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
75875d3a19aSMatthew G. Knepley       }
75975d3a19aSMatthew G. Knepley #endif
76075d3a19aSMatthew G. Knepley       /* C triangle */
76175d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
76275d3a19aSMatthew G. Knepley       orntNew[0] = -2;
76375d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
76475d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
76575d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
76675d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
76775d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
76875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
76975d3a19aSMatthew G. Knepley #if 1
77075d3a19aSMatthew G. Knepley       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
77175d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
77275d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
77375d3a19aSMatthew G. Knepley       }
77475d3a19aSMatthew G. Knepley #endif
77575d3a19aSMatthew G. Knepley       /* D triangle */
77675d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
77775d3a19aSMatthew G. Knepley       orntNew[0] = 0;
77875d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
77975d3a19aSMatthew G. Knepley       orntNew[1] = 0;
78075d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
78175d3a19aSMatthew G. Knepley       orntNew[2] = 0;
78275d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
78375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
78475d3a19aSMatthew G. Knepley #if 1
78575d3a19aSMatthew G. Knepley       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
78675d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
78775d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
78875d3a19aSMatthew G. Knepley       }
78975d3a19aSMatthew G. Knepley #endif
79075d3a19aSMatthew G. Knepley     }
79175d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
79275d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
79375d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
79475d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
79575d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
79675d3a19aSMatthew G. Knepley 
79775d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
79875d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
799297d2bf4SMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
80075d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
80175d3a19aSMatthew G. Knepley 
80275d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
80375d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
80475d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
80575d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
80675d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
80775d3a19aSMatthew G. Knepley #if 1
80875d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
80975d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
81075d3a19aSMatthew G. Knepley           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
81175d3a19aSMatthew G. Knepley         }
81275d3a19aSMatthew G. Knepley #endif
81375d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
81475d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
81575d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
81675d3a19aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
81775d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
818297d2bf4SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
81975d3a19aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
82075d3a19aSMatthew G. Knepley             if (cone[c] == f) break;
82175d3a19aSMatthew G. Knepley           }
822297d2bf4SMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
82375d3a19aSMatthew G. Knepley         }
82475d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
82575d3a19aSMatthew G. Knepley #if 1
82675d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
82775d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
82875d3a19aSMatthew G. Knepley           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
82975d3a19aSMatthew G. Knepley         }
83075d3a19aSMatthew G. Knepley #endif
83175d3a19aSMatthew G. Knepley       }
83275d3a19aSMatthew G. Knepley     }
83375d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
83475d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
83575d3a19aSMatthew G. Knepley       const PetscInt *cone;
83675d3a19aSMatthew G. Knepley 
83775d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
83875d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
83975d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
84075d3a19aSMatthew G. Knepley         PetscInt       coneNew[2];
84175d3a19aSMatthew G. Knepley         PetscInt       supportNew[2];
84275d3a19aSMatthew G. Knepley 
84375d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
84475d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
84575d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
84675d3a19aSMatthew G. Knepley #if 1
84775d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
84875d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
84975d3a19aSMatthew G. Knepley           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
85075d3a19aSMatthew G. Knepley         }
85175d3a19aSMatthew G. Knepley #endif
85275d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + (r+1)%3;
85375d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + 3;
85475d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
85575d3a19aSMatthew G. Knepley #if 1
85675d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
85775d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
85875d3a19aSMatthew G. Knepley           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
85975d3a19aSMatthew G. Knepley         }
86075d3a19aSMatthew G. Knepley #endif
86175d3a19aSMatthew G. Knepley       }
86275d3a19aSMatthew G. Knepley     }
86375d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
86475d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
86575d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
86675d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
86775d3a19aSMatthew G. Knepley       PetscInt        size, s;
86875d3a19aSMatthew G. Knepley 
86975d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
87075d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
87175d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
87275d3a19aSMatthew G. Knepley         PetscInt r = 0;
87375d3a19aSMatthew G. Knepley 
87475d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
87575d3a19aSMatthew G. Knepley         if (cone[1] == v) r = 1;
87675d3a19aSMatthew G. Knepley         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
87775d3a19aSMatthew G. Knepley       }
87875d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
87975d3a19aSMatthew G. Knepley #if 1
88075d3a19aSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
88175d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
88275d3a19aSMatthew G. Knepley         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
88375d3a19aSMatthew G. Knepley       }
88475d3a19aSMatthew G. Knepley #endif
88575d3a19aSMatthew G. Knepley     }
88675d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells*2 supports */
88775d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
88875d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
88975d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
89075d3a19aSMatthew G. Knepley       PetscInt        size, s;
89175d3a19aSMatthew G. Knepley 
89275d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
89375d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
89475d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
89575d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
89675d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
89775d3a19aSMatthew G. Knepley         PetscInt r = 0;
89875d3a19aSMatthew G. Knepley 
89975d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
90075d3a19aSMatthew G. Knepley         if      (cone[1] == f) r = 1;
90175d3a19aSMatthew G. Knepley         else if (cone[2] == f) r = 2;
90275d3a19aSMatthew G. Knepley         supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
90375d3a19aSMatthew G. Knepley         supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
90475d3a19aSMatthew G. Knepley       }
90575d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
90675d3a19aSMatthew G. Knepley #if 1
90775d3a19aSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
90875d3a19aSMatthew G. Knepley       for (p = 0; p < 2+size*2; ++p) {
90975d3a19aSMatthew G. Knepley         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
91075d3a19aSMatthew G. Knepley       }
91175d3a19aSMatthew G. Knepley #endif
91275d3a19aSMatthew G. Knepley     }
91375d3a19aSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
91475d3a19aSMatthew G. Knepley     break;
91575d3a19aSMatthew G. Knepley   case 2:
91675d3a19aSMatthew G. Knepley     /* Hex 2D */
91775d3a19aSMatthew G. Knepley     /*
91875d3a19aSMatthew G. Knepley      3---------2---------2
91975d3a19aSMatthew G. Knepley      |         |         |
92075d3a19aSMatthew G. Knepley      |    D    2    C    |
92175d3a19aSMatthew G. Knepley      |         |         |
92275d3a19aSMatthew G. Knepley      3----3----0----1----1
92375d3a19aSMatthew G. Knepley      |         |         |
92475d3a19aSMatthew G. Knepley      |    A    0    B    |
92575d3a19aSMatthew G. Knepley      |         |         |
92675d3a19aSMatthew G. Knepley      0---------0---------1
92775d3a19aSMatthew G. Knepley      */
92875d3a19aSMatthew G. Knepley     /* All cells have 4 faces */
92975d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
93075d3a19aSMatthew G. Knepley       const PetscInt  newp = (c - cStart)*4;
93175d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
93275d3a19aSMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
93375d3a19aSMatthew G. Knepley 
93475d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
93575d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
93675d3a19aSMatthew G. Knepley       /* A quad */
93775d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
93875d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
93975d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
94075d3a19aSMatthew G. Knepley       orntNew[1] = 0;
94175d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
94275d3a19aSMatthew G. Knepley       orntNew[2] = -2;
94375d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
94475d3a19aSMatthew G. Knepley       orntNew[3] = ornt[3];
94575d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
94675d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
94775d3a19aSMatthew G. Knepley #if 1
94875d3a19aSMatthew G. Knepley       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
94975d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
95075d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
95175d3a19aSMatthew G. Knepley       }
95275d3a19aSMatthew G. Knepley #endif
95375d3a19aSMatthew G. Knepley       /* B quad */
95475d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
95575d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
95675d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
95775d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
95875d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
95975d3a19aSMatthew G. Knepley       orntNew[2] = 0;
96075d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
96175d3a19aSMatthew G. Knepley       orntNew[3] = -2;
96275d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
96375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
96475d3a19aSMatthew G. Knepley #if 1
96575d3a19aSMatthew G. Knepley       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
96675d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
96775d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
96875d3a19aSMatthew G. Knepley       }
96975d3a19aSMatthew G. Knepley #endif
97075d3a19aSMatthew G. Knepley       /* C quad */
97175d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
97275d3a19aSMatthew G. Knepley       orntNew[0] = -2;
97375d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
97475d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
97575d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
97675d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
97775d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
97875d3a19aSMatthew G. Knepley       orntNew[3] = 0;
97975d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
98075d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
98175d3a19aSMatthew G. Knepley #if 1
98275d3a19aSMatthew G. Knepley       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
98375d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
98475d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
98575d3a19aSMatthew G. Knepley       }
98675d3a19aSMatthew G. Knepley #endif
98775d3a19aSMatthew G. Knepley       /* D quad */
98875d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
98975d3a19aSMatthew G. Knepley       orntNew[0] = 0;
99075d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
99175d3a19aSMatthew G. Knepley       orntNew[1] = -2;
99275d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
99375d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
99475d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
99575d3a19aSMatthew G. Knepley       orntNew[3] = ornt[3];
99675d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
99775d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
99875d3a19aSMatthew G. Knepley #if 1
99975d3a19aSMatthew G. Knepley       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
100075d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
100175d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
100275d3a19aSMatthew G. Knepley       }
100375d3a19aSMatthew G. Knepley #endif
100475d3a19aSMatthew G. Knepley     }
100575d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
100675d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
100775d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
100875d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
100975d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
101075d3a19aSMatthew G. Knepley 
101175d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
101275d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
1013455d6cd4SMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
101475d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
101575d3a19aSMatthew G. Knepley 
101675d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
101775d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
101875d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
101975d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
102075d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
102175d3a19aSMatthew G. Knepley #if 1
102275d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
102375d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
102475d3a19aSMatthew G. Knepley           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
102575d3a19aSMatthew G. Knepley         }
102675d3a19aSMatthew G. Knepley #endif
102775d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
102875d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
102975d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
103075d3a19aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
103175d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1032455d6cd4SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
103375d3a19aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
103475d3a19aSMatthew G. Knepley             if (cone[c] == f) break;
103575d3a19aSMatthew G. Knepley           }
1036455d6cd4SMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
103775d3a19aSMatthew G. Knepley         }
103875d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
103975d3a19aSMatthew G. Knepley #if 1
104075d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
104175d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
104275d3a19aSMatthew G. Knepley           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
104375d3a19aSMatthew G. Knepley         }
104475d3a19aSMatthew G. Knepley #endif
104575d3a19aSMatthew G. Knepley       }
104675d3a19aSMatthew G. Knepley     }
104775d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
104875d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
104975d3a19aSMatthew G. Knepley       const PetscInt *cone;
105075d3a19aSMatthew G. Knepley       PetscInt        coneNew[2], supportNew[2];
105175d3a19aSMatthew G. Knepley 
105275d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
105375d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
105475d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
105575d3a19aSMatthew G. Knepley 
105675d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
105775d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
105875d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
105975d3a19aSMatthew G. Knepley #if 1
106075d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
106175d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
106275d3a19aSMatthew G. Knepley           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
106375d3a19aSMatthew G. Knepley         }
106475d3a19aSMatthew G. Knepley #endif
106575d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + r;
106675d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + (r+1)%4;
106775d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
106875d3a19aSMatthew G. Knepley #if 1
106975d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
107075d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
107175d3a19aSMatthew G. Knepley           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
107275d3a19aSMatthew G. Knepley         }
107375d3a19aSMatthew G. Knepley #endif
107475d3a19aSMatthew G. Knepley       }
107575d3a19aSMatthew G. Knepley     }
107675d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
107775d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
107875d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
107975d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
108075d3a19aSMatthew G. Knepley       PetscInt        size, s;
108175d3a19aSMatthew G. Knepley 
108275d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
108375d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
108475d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
108575d3a19aSMatthew G. Knepley         PetscInt r = 0;
108675d3a19aSMatthew G. Knepley 
108775d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
108875d3a19aSMatthew G. Knepley         if (cone[1] == v) r = 1;
108975d3a19aSMatthew G. Knepley         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
109075d3a19aSMatthew G. Knepley       }
109175d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
109275d3a19aSMatthew G. Knepley #if 1
109375d3a19aSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
109475d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
109575d3a19aSMatthew G. Knepley         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
109675d3a19aSMatthew G. Knepley       }
109775d3a19aSMatthew G. Knepley #endif
109875d3a19aSMatthew G. Knepley     }
109975d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells supports */
110075d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
110175d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
110275d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
110375d3a19aSMatthew G. Knepley       PetscInt        size, s;
110475d3a19aSMatthew G. Knepley 
110575d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
110675d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
110775d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
110875d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
110975d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
111075d3a19aSMatthew G. Knepley         PetscInt r = 0;
111175d3a19aSMatthew G. Knepley 
111275d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
111375d3a19aSMatthew G. Knepley         if      (cone[1] == f) r = 1;
111475d3a19aSMatthew G. Knepley         else if (cone[2] == f) r = 2;
111575d3a19aSMatthew G. Knepley         else if (cone[3] == f) r = 3;
111675d3a19aSMatthew G. Knepley         supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r;
111775d3a19aSMatthew G. Knepley       }
111875d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
111975d3a19aSMatthew G. Knepley #if 1
112075d3a19aSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
112175d3a19aSMatthew G. Knepley       for (p = 0; p < 2+size; ++p) {
112275d3a19aSMatthew G. Knepley         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
112375d3a19aSMatthew G. Knepley       }
112475d3a19aSMatthew G. Knepley #endif
112575d3a19aSMatthew G. Knepley     }
112675d3a19aSMatthew G. Knepley     /* Cell vertices have 4 supports */
112775d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
112875d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
112975d3a19aSMatthew G. Knepley       PetscInt       supportNew[4];
113075d3a19aSMatthew G. Knepley 
113175d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
113275d3a19aSMatthew G. Knepley         supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
113375d3a19aSMatthew G. Knepley       }
113475d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
113575d3a19aSMatthew G. Knepley     }
1136da00770fSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
113775d3a19aSMatthew G. Knepley     break;
113875d3a19aSMatthew G. Knepley   case 3:
113975d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
114075d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
114175d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
114275d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
114375d3a19aSMatthew G. Knepley     /* Interior cells have 3 faces */
114475d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
114575d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*4;
114675d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
114775d3a19aSMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
114875d3a19aSMatthew G. Knepley 
114975d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
115075d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
115175d3a19aSMatthew G. Knepley       /* A triangle */
115275d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
115375d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
115475d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
115575d3a19aSMatthew G. Knepley       orntNew[1] = -2;
115675d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
115775d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
115875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
115975d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
116075d3a19aSMatthew G. Knepley #if 1
116175d3a19aSMatthew G. Knepley       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
116275d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
116375d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
116475d3a19aSMatthew G. Knepley       }
116575d3a19aSMatthew G. Knepley #endif
116675d3a19aSMatthew G. Knepley       /* B triangle */
116775d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
116875d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
116975d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
117075d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
117175d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
117275d3a19aSMatthew G. Knepley       orntNew[2] = -2;
117375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
117475d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
117575d3a19aSMatthew G. Knepley #if 1
117675d3a19aSMatthew G. Knepley       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
117775d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
117875d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
117975d3a19aSMatthew G. Knepley       }
118075d3a19aSMatthew G. Knepley #endif
118175d3a19aSMatthew G. Knepley       /* C triangle */
118275d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
118375d3a19aSMatthew G. Knepley       orntNew[0] = -2;
118475d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
118575d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
118675d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
118775d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
118875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
118975d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
119075d3a19aSMatthew G. Knepley #if 1
119175d3a19aSMatthew G. Knepley       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
119275d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
119375d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
119475d3a19aSMatthew G. Knepley       }
119575d3a19aSMatthew G. Knepley #endif
119675d3a19aSMatthew G. Knepley       /* D triangle */
119775d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
119875d3a19aSMatthew G. Knepley       orntNew[0] = 0;
119975d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
120075d3a19aSMatthew G. Knepley       orntNew[1] = 0;
120175d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
120275d3a19aSMatthew G. Knepley       orntNew[2] = 0;
120375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
120475d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
120575d3a19aSMatthew G. Knepley #if 1
120675d3a19aSMatthew G. Knepley       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
120775d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
120875d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
120975d3a19aSMatthew G. Knepley       }
121075d3a19aSMatthew G. Knepley #endif
121175d3a19aSMatthew G. Knepley     }
121275d3a19aSMatthew G. Knepley     /*
121375d3a19aSMatthew G. Knepley      2----3----3
121475d3a19aSMatthew G. Knepley      |         |
121575d3a19aSMatthew G. Knepley      |    B    |
121675d3a19aSMatthew G. Knepley      |         |
121775d3a19aSMatthew G. Knepley      0----4--- 1
121875d3a19aSMatthew G. Knepley      |         |
121975d3a19aSMatthew G. Knepley      |    A    |
122075d3a19aSMatthew G. Knepley      |         |
122175d3a19aSMatthew G. Knepley      0----2----1
122275d3a19aSMatthew G. Knepley      */
122375d3a19aSMatthew G. Knepley     /* Hybrid cells have 4 faces */
122475d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
122575d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
122675d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
122775d3a19aSMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
122875d3a19aSMatthew G. Knepley 
122975d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
123075d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
123175d3a19aSMatthew G. Knepley       /* A quad */
123275d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
123375d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
123475d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
123575d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
123675d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax);
123775d3a19aSMatthew G. Knepley       orntNew[2] = 0;
123875d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
123975d3a19aSMatthew G. Knepley       orntNew[3] = 0;
124075d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
124175d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
124275d3a19aSMatthew G. Knepley #if 1
124375d3a19aSMatthew G. Knepley       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
124475d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
124575d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
124675d3a19aSMatthew G. Knepley       }
124775d3a19aSMatthew G. Knepley #endif
124875d3a19aSMatthew G. Knepley       /* B quad */
124975d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
125075d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
125175d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
125275d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
125375d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
125475d3a19aSMatthew G. Knepley       orntNew[2] = 0;
125575d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax);
125675d3a19aSMatthew G. Knepley       orntNew[3] = 0;
125775d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
125875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
125975d3a19aSMatthew G. Knepley #if 1
126075d3a19aSMatthew G. Knepley       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
126175d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
126275d3a19aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
126375d3a19aSMatthew G. Knepley       }
126475d3a19aSMatthew G. Knepley #endif
126575d3a19aSMatthew G. Knepley     }
126675d3a19aSMatthew G. Knepley     /* Interior split faces have 2 vertices and the same cells as the parent */
126775d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
126875d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
126975d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
127075d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
127175d3a19aSMatthew G. Knepley 
127275d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
127375d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
1274297d2bf4SMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
127575d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
127675d3a19aSMatthew G. Knepley 
127775d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
127875d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
127975d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
128075d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
128175d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
128275d3a19aSMatthew G. Knepley #if 1
128375d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
128475d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
128575d3a19aSMatthew G. Knepley           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
128675d3a19aSMatthew G. Knepley         }
128775d3a19aSMatthew G. Knepley #endif
128875d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
128975d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
129075d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
129175d3a19aSMatthew G. Knepley           if (support[s] >= cMax) {
129275d3a19aSMatthew G. Knepley             supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
129375d3a19aSMatthew G. Knepley           } else {
129475d3a19aSMatthew G. Knepley             ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
129575d3a19aSMatthew G. Knepley             ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1296297d2bf4SMatthew G. Knepley             ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
129775d3a19aSMatthew G. Knepley             for (c = 0; c < coneSize; ++c) {
129875d3a19aSMatthew G. Knepley               if (cone[c] == f) break;
129975d3a19aSMatthew G. Knepley             }
1300297d2bf4SMatthew G. Knepley             supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
130175d3a19aSMatthew G. Knepley           }
130275d3a19aSMatthew G. Knepley         }
130375d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
130475d3a19aSMatthew G. Knepley #if 1
130575d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
130675d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
130775d3a19aSMatthew G. Knepley           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
130875d3a19aSMatthew G. Knepley         }
130975d3a19aSMatthew G. Knepley #endif
131075d3a19aSMatthew G. Knepley       }
131175d3a19aSMatthew G. Knepley     }
131275d3a19aSMatthew G. Knepley     /* Interior cell faces have 2 vertices and 2 cells */
131375d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
131475d3a19aSMatthew G. Knepley       const PetscInt *cone;
131575d3a19aSMatthew G. Knepley 
131675d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
131775d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
131875d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
131975d3a19aSMatthew G. Knepley         PetscInt       coneNew[2];
132075d3a19aSMatthew G. Knepley         PetscInt       supportNew[2];
132175d3a19aSMatthew G. Knepley 
132275d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
132375d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
132475d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
132575d3a19aSMatthew G. Knepley #if 1
132675d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
132775d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
132875d3a19aSMatthew G. Knepley           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
132975d3a19aSMatthew G. Knepley         }
133075d3a19aSMatthew G. Knepley #endif
133175d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + (r+1)%3;
133275d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + 3;
133375d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
133475d3a19aSMatthew G. Knepley #if 1
133575d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
133675d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
133775d3a19aSMatthew G. Knepley           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
133875d3a19aSMatthew G. Knepley         }
133975d3a19aSMatthew G. Knepley #endif
134075d3a19aSMatthew G. Knepley       }
134175d3a19aSMatthew G. Knepley     }
134275d3a19aSMatthew G. Knepley     /* Interior hybrid faces have 2 vertices and the same cells */
134375d3a19aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
134475d3a19aSMatthew G. Knepley       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
134575d3a19aSMatthew G. Knepley       const PetscInt *cone;
134675d3a19aSMatthew G. Knepley       const PetscInt *support;
134775d3a19aSMatthew G. Knepley       PetscInt        coneNew[2];
134875d3a19aSMatthew G. Knepley       PetscInt        supportNew[2];
134975d3a19aSMatthew G. Knepley       PetscInt        size, s, r;
135075d3a19aSMatthew G. Knepley 
135175d3a19aSMatthew G. Knepley       ierr       = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
135275d3a19aSMatthew G. Knepley       coneNew[0] = vStartNew + (cone[0] - vStart);
135375d3a19aSMatthew G. Knepley       coneNew[1] = vStartNew + (cone[1] - vStart);
135475d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
135575d3a19aSMatthew G. Knepley #if 1
135675d3a19aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
135775d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
135875d3a19aSMatthew G. Knepley         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
135975d3a19aSMatthew G. Knepley       }
136075d3a19aSMatthew G. Knepley #endif
136175d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
136275d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
136375d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
136475d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
136575d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r) {
136675d3a19aSMatthew G. Knepley           if (cone[r+2] == f) break;
136775d3a19aSMatthew G. Knepley         }
136875d3a19aSMatthew G. Knepley         supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
136975d3a19aSMatthew G. Knepley       }
137075d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
137175d3a19aSMatthew G. Knepley #if 1
137275d3a19aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
137375d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
137475d3a19aSMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
137575d3a19aSMatthew G. Knepley       }
137675d3a19aSMatthew G. Knepley #endif
137775d3a19aSMatthew G. Knepley     }
137875d3a19aSMatthew G. Knepley     /* Cell hybrid faces have 2 vertices and 2 cells */
137975d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
138075d3a19aSMatthew G. Knepley       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
138175d3a19aSMatthew G. Knepley       const PetscInt *cone;
138275d3a19aSMatthew G. Knepley       PetscInt        coneNew[2];
138375d3a19aSMatthew G. Knepley       PetscInt        supportNew[2];
138475d3a19aSMatthew G. Knepley 
138575d3a19aSMatthew G. Knepley       ierr       = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
138675d3a19aSMatthew G. Knepley       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
138775d3a19aSMatthew G. Knepley       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
138875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
138975d3a19aSMatthew G. Knepley #if 1
139075d3a19aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
139175d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
139275d3a19aSMatthew G. Knepley         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
139375d3a19aSMatthew G. Knepley       }
139475d3a19aSMatthew G. Knepley #endif
139575d3a19aSMatthew G. Knepley       supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
139675d3a19aSMatthew G. Knepley       supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
139775d3a19aSMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
139875d3a19aSMatthew G. Knepley #if 1
139975d3a19aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
140075d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
140175d3a19aSMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
140275d3a19aSMatthew G. Knepley       }
140375d3a19aSMatthew G. Knepley #endif
140475d3a19aSMatthew G. Knepley     }
140575d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
140675d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
140775d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
140875d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
140975d3a19aSMatthew G. Knepley       PetscInt        size, s;
141075d3a19aSMatthew G. Knepley 
141175d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
141275d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
141375d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
141475d3a19aSMatthew G. Knepley         if (support[s] >= fMax) {
141575d3a19aSMatthew G. Knepley           supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax);
141675d3a19aSMatthew G. Knepley         } else {
141775d3a19aSMatthew G. Knepley           PetscInt r = 0;
141875d3a19aSMatthew G. Knepley 
141975d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
142075d3a19aSMatthew G. Knepley           if (cone[1] == v) r = 1;
142175d3a19aSMatthew G. Knepley           supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
142275d3a19aSMatthew G. Knepley         }
142375d3a19aSMatthew G. Knepley       }
142475d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
142575d3a19aSMatthew G. Knepley #if 1
142675d3a19aSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
142775d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
142875d3a19aSMatthew G. Knepley         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
142975d3a19aSMatthew G. Knepley       }
143075d3a19aSMatthew G. Knepley #endif
143175d3a19aSMatthew G. Knepley     }
143275d3a19aSMatthew G. Knepley     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
143375d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
143475d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
143575d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
143675d3a19aSMatthew G. Knepley       PetscInt        size, newSize = 2, s;
143775d3a19aSMatthew G. Knepley 
143875d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
143975d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
144075d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
144175d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
144275d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
144375d3a19aSMatthew G. Knepley         PetscInt r = 0;
144475d3a19aSMatthew G. Knepley 
144575d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
144675d3a19aSMatthew G. Knepley         if (support[s] >= cMax) {
144775d3a19aSMatthew G. Knepley           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax);
144875d3a19aSMatthew G. Knepley 
144975d3a19aSMatthew G. Knepley           newSize += 1;
145075d3a19aSMatthew G. Knepley         } else {
145175d3a19aSMatthew G. Knepley           if      (cone[1] == f) r = 1;
145275d3a19aSMatthew G. Knepley           else if (cone[2] == f) r = 2;
145375d3a19aSMatthew G. Knepley           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
145475d3a19aSMatthew G. Knepley           supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r;
145575d3a19aSMatthew G. Knepley 
145675d3a19aSMatthew G. Knepley           newSize += 2;
145775d3a19aSMatthew G. Knepley         }
145875d3a19aSMatthew G. Knepley       }
145975d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
146075d3a19aSMatthew G. Knepley #if 1
146175d3a19aSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
146275d3a19aSMatthew G. Knepley       for (p = 0; p < newSize; ++p) {
146375d3a19aSMatthew G. Knepley         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
146475d3a19aSMatthew G. Knepley       }
146575d3a19aSMatthew G. Knepley #endif
146675d3a19aSMatthew G. Knepley     }
146775d3a19aSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
146875d3a19aSMatthew G. Knepley     break;
1469b5da9499SMatthew G. Knepley   case 5:
1470b5da9499SMatthew G. Knepley     /* Simplicial 3D */
1471b5da9499SMatthew G. Knepley     /* All cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
1472b5da9499SMatthew G. Knepley     ierr = DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);CHKERRQ(ierr);
1473b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1474b5da9499SMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*8;
1475b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt;
1476b5da9499SMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
1477b5da9499SMatthew G. Knepley 
1478b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1479b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1480b5da9499SMatthew G. Knepley       /* A tetrahedron: {0, a, c, d} */
1481518a8359SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
1482b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1483518a8359SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
1484b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1485518a8359SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
1486b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1487b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
1488b5da9499SMatthew G. Knepley       orntNew[3] = 0;
1489b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1490b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1491b5da9499SMatthew G. Knepley #if 1
1492b5da9499SMatthew G. Knepley       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
1493b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1494b5da9499SMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1495b5da9499SMatthew G. Knepley       }
1496b5da9499SMatthew G. Knepley #endif
1497b5da9499SMatthew G. Knepley       /* B tetrahedron: {a, 1, b, e} */
1498518a8359SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
1499b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1500518a8359SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
1501b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1502b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
1503b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1504518a8359SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
1505b5da9499SMatthew G. Knepley       orntNew[3] = ornt[3];
1506b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1507b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1508b5da9499SMatthew G. Knepley #if 1
1509b5da9499SMatthew G. Knepley       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
1510b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1511b5da9499SMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1512b5da9499SMatthew G. Knepley       }
1513b5da9499SMatthew G. Knepley #endif
1514b5da9499SMatthew G. Knepley       /* C tetrahedron: {c, b, 2, f} */
1515518a8359SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
1516b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1517b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
1518b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1519518a8359SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
1520b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1521518a8359SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
1522b5da9499SMatthew G. Knepley       orntNew[3] = ornt[3];
1523b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1524b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1525b5da9499SMatthew G. Knepley #if 1
1526b5da9499SMatthew G. Knepley       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
1527b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1528b5da9499SMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1529b5da9499SMatthew G. Knepley       }
1530b5da9499SMatthew G. Knepley #endif
1531b5da9499SMatthew G. Knepley       /* D tetrahedron: {d, e, f, 3} */
1532b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
1533b5da9499SMatthew G. Knepley       orntNew[0] = 0;
1534518a8359SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
1535b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1536518a8359SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
1537b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1538518a8359SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
1539b5da9499SMatthew G. Knepley       orntNew[3] = ornt[3];
1540b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
1541b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
1542b5da9499SMatthew G. Knepley #if 1
1543b5da9499SMatthew G. Knepley       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
1544b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1545b5da9499SMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1546b5da9499SMatthew G. Knepley       }
1547b5da9499SMatthew G. Knepley #endif
1548b5da9499SMatthew G. Knepley       /* A' tetrahedron: {d, a, c, f} */
1549b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
1550b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1551b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
1552b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1553b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + 3;
1554b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -((-(ornt[2]+1)+2)%3+1) : (ornt[2]+2)%3;
1555b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
1556b5da9499SMatthew G. Knepley       orntNew[3] = 0;
1557b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
1558b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
1559b5da9499SMatthew G. Knepley #if 1
1560b5da9499SMatthew G. Knepley       if ((newp+4 < cStartNew) || (newp+4 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+4, cStartNew, cEndNew);
1561b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1562b5da9499SMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1563b5da9499SMatthew G. Knepley       }
1564b5da9499SMatthew G. Knepley #endif
1565b5da9499SMatthew G. Knepley       /* B' tetrahedron: {e, b, a, f} */
1566b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
1567b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1568b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[3] - fStart)*4 + 3;
1569b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -((-(ornt[3]+1)+1)%3+1) : (ornt[3]+1)%3;
1570b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
1571b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1572b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
1573b5da9499SMatthew G. Knepley       orntNew[3] = 0;
1574b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
1575b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
1576b5da9499SMatthew G. Knepley #if 1
1577b5da9499SMatthew G. Knepley       if ((newp+5 < cStartNew) || (newp+5 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+5, cStartNew, cEndNew);
1578b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1579b5da9499SMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1580b5da9499SMatthew G. Knepley       }
1581b5da9499SMatthew G. Knepley #endif
1582b5da9499SMatthew G. Knepley       /* C' tetrahedron: {b, f, c, a} */
1583b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
1584b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1585b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
1586b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1587b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[0] - fStart)*4 + 3;
1588b5da9499SMatthew G. Knepley       orntNew[2] = ornt[0] < 0 ? (-(ornt[0]+1)+1)%3 : -((ornt[0]+1)%3+1);
1589b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
1590b5da9499SMatthew G. Knepley       orntNew[3] = -1;
1591b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
1592b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
1593b5da9499SMatthew G. Knepley #if 1
1594b5da9499SMatthew G. Knepley       if ((newp+6 < cStartNew) || (newp+6 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+6, cStartNew, cEndNew);
1595b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1596b5da9499SMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1597b5da9499SMatthew G. Knepley       }
1598b5da9499SMatthew G. Knepley #endif
1599b5da9499SMatthew G. Knepley       /* D' tetrahedron: {f, e, d, a} */
1600b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
1601b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1602b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
1603b5da9499SMatthew G. Knepley       orntNew[1] = -3;
1604b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
1605b5da9499SMatthew G. Knepley       orntNew[2] = -2;
1606b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[1] - fStart)*4 + 3;
1607b5da9499SMatthew G. Knepley       orntNew[3] = ornt[2];
1608b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
1609b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
1610b5da9499SMatthew G. Knepley #if 1
1611b5da9499SMatthew G. Knepley       if ((newp+7 < cStartNew) || (newp+7 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+7, cStartNew, cEndNew);
1612b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1613b5da9499SMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1614b5da9499SMatthew G. Knepley       }
1615b5da9499SMatthew G. Knepley #endif
1616b5da9499SMatthew G. Knepley     }
1617b5da9499SMatthew G. Knepley     /* Split faces have 3 edges and the same cells as the parent */
1618b5da9499SMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
1619b5da9499SMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
1620b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
1621b5da9499SMatthew G. Knepley       const PetscInt  newp = fStartNew + (f - fStart)*4;
1622b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt, *support;
1623b5da9499SMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3], coneSize, supportSize, s;
1624b5da9499SMatthew G. Knepley 
1625b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1626b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
1627b5da9499SMatthew G. Knepley       /* A triangle */
1628b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
1629b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1630b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
1631b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1632b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
1633b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1634b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1635b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1636b5da9499SMatthew G. Knepley #if 1
1637b5da9499SMatthew G. Knepley       if ((newp+0 < fStartNew) || (newp+0 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+0, fStartNew, fEndNew);
1638b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1639b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1640b5da9499SMatthew G. Knepley       }
1641b5da9499SMatthew G. Knepley #endif
1642b5da9499SMatthew G. Knepley       /* B triangle */
1643b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
1644b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1645b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
1646b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1647b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
1648b5da9499SMatthew G. Knepley       orntNew[2] = -2;
1649b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1650b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1651b5da9499SMatthew G. Knepley #if 1
1652b5da9499SMatthew G. Knepley       if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+1, fStartNew, fEndNew);
1653b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1654b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1655b5da9499SMatthew G. Knepley       }
1656b5da9499SMatthew G. Knepley #endif
1657b5da9499SMatthew G. Knepley       /* C triangle */
1658b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
1659b5da9499SMatthew G. Knepley       orntNew[0] = -2;
1660b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
1661b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1662b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
1663b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1664b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1665b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1666b5da9499SMatthew G. Knepley #if 1
1667b5da9499SMatthew G. Knepley       if ((newp+2 < fStartNew) || (newp+2 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+2, fStartNew, fEndNew);
1668b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1669b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1670b5da9499SMatthew G. Knepley       }
1671b5da9499SMatthew G. Knepley #endif
1672b5da9499SMatthew G. Knepley       /* D triangle */
1673b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
1674b5da9499SMatthew G. Knepley       orntNew[0] = 0;
1675b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
1676b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1677b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
1678b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1679b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
1680b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
1681b5da9499SMatthew G. Knepley #if 1
1682b5da9499SMatthew G. Knepley       if ((newp+3 < fStartNew) || (newp+3 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+3, fStartNew, fEndNew);
1683b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1684b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1685b5da9499SMatthew G. Knepley       }
1686b5da9499SMatthew G. Knepley #endif
1687b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1688b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1689b5da9499SMatthew G. Knepley       for (r = 0; r < 4; ++r) {
1690b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
1691b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1692b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1693b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1694b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
1695b5da9499SMatthew G. Knepley             if (cone[c] == f) break;
1696b5da9499SMatthew G. Knepley           }
1697b5da9499SMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : (ornt[c] < 0 ? faces[c*3+(-(ornt[c]+1)+1+3-r)%3] : faces[c*3+r]));
1698b5da9499SMatthew G. Knepley         }
1699b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp+r, supportRef);CHKERRQ(ierr);
1700b5da9499SMatthew G. Knepley #if 1
1701b5da9499SMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1702b5da9499SMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
1703b5da9499SMatthew G. Knepley           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
1704b5da9499SMatthew G. Knepley         }
1705b5da9499SMatthew G. Knepley #endif
1706b5da9499SMatthew G. Knepley       }
1707b5da9499SMatthew G. Knepley     }
1708b5da9499SMatthew G. Knepley     /* Interior faces have 3 edges and 2 cells */
1709b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1710b5da9499SMatthew G. Knepley       PetscInt        newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8;
1711b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt;
1712b5da9499SMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
1713b5da9499SMatthew G. Knepley       PetscInt        supportNew[2];
1714b5da9499SMatthew G. Knepley 
1715b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1716b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1717b5da9499SMatthew G. Knepley       /* Face A: {c, a, d} */
1718b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+0)%3 : (ornt[0]+2)%3);
1719b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1720b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+0)%3 : (ornt[1]+2)%3);
1721b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1] < 0 ? -2 : 0;
1722b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+0)%3 : (ornt[2]+2)%3);
1723b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -2 : 0;
1724b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1725b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1726b5da9499SMatthew G. Knepley #if 1
1727b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1728b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1729b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1730b5da9499SMatthew G. Knepley       }
1731b5da9499SMatthew G. Knepley #endif
1732b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0;
1733b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 0+4;
1734b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1735b5da9499SMatthew G. Knepley #if 1
1736b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1737b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1738b5da9499SMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1739b5da9499SMatthew G. Knepley       }
1740b5da9499SMatthew G. Knepley #endif
1741b5da9499SMatthew G. Knepley       ++newp;
1742b5da9499SMatthew G. Knepley       /* Face B: {a, b, e} */
1743b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+2)%3 : (ornt[0]+0)%3);
1744b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1745b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+2)%3 : (ornt[3]+0)%3);
1746b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1747b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+1)%3 : (ornt[1]+1)%3);
1748b5da9499SMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? -2 : 0;
1749b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1750b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1751b5da9499SMatthew G. Knepley #if 1
1752b5da9499SMatthew G. Knepley       if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+1, fStartNew, fEndNew);
1753b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1754b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1755b5da9499SMatthew G. Knepley       }
1756b5da9499SMatthew G. Knepley #endif
1757b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1;
1758b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 1+4;
1759b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1760b5da9499SMatthew G. Knepley #if 1
1761b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1762b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1763b5da9499SMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1764b5da9499SMatthew G. Knepley       }
1765b5da9499SMatthew G. Knepley #endif
1766b5da9499SMatthew G. Knepley       ++newp;
1767b5da9499SMatthew G. Knepley       /* Face C: {c, f, b} */
1768b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+2)%3 : (ornt[2]+0)%3);
1769b5da9499SMatthew G. Knepley       orntNew[0] = ornt[2] < 0 ? -2 : 0;
1770b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+0)%3 : (ornt[3]+2)%3);
1771b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1772b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+1)%3 : (ornt[0]+1)%3);
1773b5da9499SMatthew G. Knepley       orntNew[2] = ornt[0] < 0 ? -2 : 0;
1774b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1775b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1776b5da9499SMatthew G. Knepley #if 1
1777b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1778b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1779b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1780b5da9499SMatthew G. Knepley       }
1781b5da9499SMatthew G. Knepley #endif
1782b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 2;
1783b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
1784b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1785b5da9499SMatthew G. Knepley #if 1
1786b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1787b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1788b5da9499SMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1789b5da9499SMatthew G. Knepley       }
1790b5da9499SMatthew G. Knepley #endif
1791b5da9499SMatthew G. Knepley       ++newp;
1792b5da9499SMatthew G. Knepley       /* Face D: {d, e, f} */
1793b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+2)%3 : (ornt[1]+0)%3);
1794b5da9499SMatthew G. Knepley       orntNew[0] = ornt[1] < 0 ? -2 : 0;
1795b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+1)%3 : (ornt[3]+1)%3);
1796b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1797b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+1)%3 : (ornt[2]+1)%3);
1798b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -2 : 0;
1799b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1800b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1801b5da9499SMatthew G. Knepley #if 1
1802b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1803b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1804b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1805b5da9499SMatthew G. Knepley       }
1806b5da9499SMatthew G. Knepley #endif
1807b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 3;
1808b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
1809b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1810b5da9499SMatthew G. Knepley #if 1
1811b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1812b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1813b5da9499SMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1814b5da9499SMatthew G. Knepley       }
1815b5da9499SMatthew G. Knepley #endif
1816b5da9499SMatthew G. Knepley       ++newp;
1817b5da9499SMatthew G. Knepley       /* Face E: {d, f, a} */
1818b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+1)%3 : (ornt[2]+1)%3);
1819b5da9499SMatthew G. Knepley       orntNew[0] = ornt[2] < 0 ? 0 : -2;
1820b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1821b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1822b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+0)%3 : (ornt[1]+2)%3);
1823b5da9499SMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? -2 : 0;
1824b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1825b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1826b5da9499SMatthew G. Knepley #if 1
1827b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1828b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1829b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1830b5da9499SMatthew G. Knepley       }
1831b5da9499SMatthew G. Knepley #endif
1832b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0+4;
1833b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
1834b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1835b5da9499SMatthew G. Knepley #if 1
1836b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1837b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1838b5da9499SMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1839b5da9499SMatthew G. Knepley       }
1840b5da9499SMatthew G. Knepley #endif
1841b5da9499SMatthew G. Knepley       ++newp;
1842b5da9499SMatthew G. Knepley       /* Face F: {c, a, f} */
1843b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+0)%3 : (ornt[0]+2)%3);
1844b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1845b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1846b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1847b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+2)%3 : (ornt[2]+0)%3);
1848b5da9499SMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? 0 : -2;
1849b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1850b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1851b5da9499SMatthew G. Knepley #if 1
1852b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1853b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1854b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1855b5da9499SMatthew G. Knepley       }
1856b5da9499SMatthew G. Knepley #endif
1857b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0+4;
1858b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
1859b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1860b5da9499SMatthew G. Knepley #if 1
1861b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1862b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1863b5da9499SMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1864b5da9499SMatthew G. Knepley       }
1865b5da9499SMatthew G. Knepley #endif
1866b5da9499SMatthew G. Knepley       ++newp;
1867b5da9499SMatthew G. Knepley       /* Face G: {e, a, f} */
1868b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+1)%3 : (ornt[1]+1)%3);
1869b5da9499SMatthew G. Knepley       orntNew[0] = ornt[1] < 0 ? -2 : 0;
1870b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1871b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1872b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+1)%3 : (ornt[3]+1)%3);
1873b5da9499SMatthew G. Knepley       orntNew[2] = ornt[3] < 0 ? 0 : -2;
1874b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1875b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1876b5da9499SMatthew G. Knepley #if 1
1877b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1878b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1879b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1880b5da9499SMatthew G. Knepley       }
1881b5da9499SMatthew G. Knepley #endif
1882b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1+4;
1883b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
1884b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1885b5da9499SMatthew G. Knepley #if 1
1886b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1887b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1888b5da9499SMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1889b5da9499SMatthew G. Knepley       }
1890b5da9499SMatthew G. Knepley #endif
1891b5da9499SMatthew G. Knepley       ++newp;
1892b5da9499SMatthew G. Knepley       /* Face H: {a, b, f} */
1893b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+2)%3 : (ornt[0]+0)%3);
1894b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1895b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+0)%3 : (ornt[3]+2)%3);
1896b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? 0 : -2;
1897b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1898b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1899b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1900b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1901b5da9499SMatthew G. Knepley #if 1
1902b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1903b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1904b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1905b5da9499SMatthew G. Knepley       }
1906b5da9499SMatthew G. Knepley #endif
1907b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1+4;
1908b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
1909b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1910b5da9499SMatthew G. Knepley #if 1
1911b5da9499SMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1912b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1913b5da9499SMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1914b5da9499SMatthew G. Knepley       }
1915b5da9499SMatthew G. Knepley #endif
1916b5da9499SMatthew G. Knepley       ++newp;
1917b5da9499SMatthew G. Knepley     }
1918b5da9499SMatthew G. Knepley     /* Split Edges have 2 vertices and the same faces as the parent */
1919b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
1920b5da9499SMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
1921b5da9499SMatthew G. Knepley 
1922b5da9499SMatthew G. Knepley       for (r = 0; r < 2; ++r) {
1923b5da9499SMatthew G. Knepley         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
1924b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
1925b5da9499SMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
1926b5da9499SMatthew G. Knepley 
1927b5da9499SMatthew G. Knepley         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
1928b5da9499SMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
1929b5da9499SMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
1930b5da9499SMatthew G. Knepley         coneNew[(r+1)%2] = newv;
1931b5da9499SMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1932b5da9499SMatthew G. Knepley #if 1
1933b5da9499SMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
1934b5da9499SMatthew G. Knepley         for (p = 0; p < 2; ++p) {
1935b5da9499SMatthew G. Knepley           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1936b5da9499SMatthew G. Knepley         }
1937b5da9499SMatthew G. Knepley #endif
1938b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
1939b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
1940b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
1941b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1942b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1943b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1944b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
1945b5da9499SMatthew G. Knepley             if (cone[c] == e) break;
1946b5da9499SMatthew G. Knepley           }
1947b5da9499SMatthew G. Knepley           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
1948b5da9499SMatthew G. Knepley         }
1949b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1950b5da9499SMatthew G. Knepley #if 1
1951b5da9499SMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
1952b5da9499SMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
1953b5da9499SMatthew G. Knepley           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
1954b5da9499SMatthew G. Knepley         }
1955b5da9499SMatthew G. Knepley #endif
1956b5da9499SMatthew G. Knepley       }
1957b5da9499SMatthew G. Knepley     }
195886f0afeeSMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
1959b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
1960b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt, *support;
1961b5da9499SMatthew G. Knepley       PetscInt        coneSize, supportSize, s;
1962b5da9499SMatthew G. Knepley 
1963b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1964b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1965b5da9499SMatthew G. Knepley       for (r = 0; r < 3; ++r) {
1966b5da9499SMatthew G. Knepley         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
1967b5da9499SMatthew G. Knepley         PetscInt        coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
1968b5da9499SMatthew G. Knepley         PetscInt        fint[24] = { 1,  7, -1, -1,  0,  5,
1969b5da9499SMatthew G. Knepley                                     -1, -1,  1,  6,  0,  4,
1970b5da9499SMatthew G. Knepley                                      2,  5,  3,  4, -1, -1,
1971b5da9499SMatthew G. Knepley                                     -1, -1,  3,  6,  2,  7};
1972b5da9499SMatthew G. Knepley 
1973b5da9499SMatthew G. Knepley         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1974b5da9499SMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
1975b5da9499SMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
1976b5da9499SMatthew G. Knepley         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1977b5da9499SMatthew G. Knepley #if 1
1978b5da9499SMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
1979b5da9499SMatthew G. Knepley         for (p = 0; p < 2; ++p) {
1980b5da9499SMatthew G. Knepley           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1981b5da9499SMatthew G. Knepley         }
1982b5da9499SMatthew G. Knepley #endif
1983b5da9499SMatthew G. Knepley         supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
1984b5da9499SMatthew G. Knepley         supportRef[1] = fStartNew + (f - fStart)*4 + 3;
1985b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
1986b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1987b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1988b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1989b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
199086f0afeeSMatthew G. Knepley           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
199186f0afeeSMatthew G. Knepley           er   = ornt[c] < 0 ? (-(ornt[c]+1) + 2-r)%3 : (ornt[c] + r)%3;
1992b5da9499SMatthew G. Knepley           if (er == eint[c]) {
1993b5da9499SMatthew G. Knepley             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
1994b5da9499SMatthew G. Knepley           } else {
1995b5da9499SMatthew G. Knepley             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
1996b5da9499SMatthew G. Knepley             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
1997b5da9499SMatthew G. Knepley           }
1998b5da9499SMatthew G. Knepley         }
1999b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2000b5da9499SMatthew G. Knepley #if 1
2001b5da9499SMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2002b5da9499SMatthew G. Knepley         for (p = 0; p < intFaces; ++p) {
2003b5da9499SMatthew G. Knepley           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
2004b5da9499SMatthew G. Knepley         }
2005b5da9499SMatthew G. Knepley #endif
2006b5da9499SMatthew G. Knepley       }
2007b5da9499SMatthew G. Knepley     }
2008b5da9499SMatthew G. Knepley     /* Interior edges have 2 vertices and 4 faces */
2009b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
2010b5da9499SMatthew G. Knepley       const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2011b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt, *fcone;
20124a40f731SMatthew G. Knepley       PetscInt        coneNew[2], supportNew[4], find;
2013b5da9499SMatthew G. Knepley 
2014b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2015b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2016b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, cone[0], &fcone);CHKERRQ(ierr);
201742525629SMatthew G. Knepley       find = GetTriEdge_Static(ornt[0], 0);
2018b5da9499SMatthew G. Knepley       coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
2019b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, cone[2], &fcone);CHKERRQ(ierr);
202042525629SMatthew G. Knepley       find = GetTriEdge_Static(ornt[2], 1);
2021b5da9499SMatthew G. Knepley       coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
2022b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2023b5da9499SMatthew G. Knepley #if 1
2024b5da9499SMatthew G. Knepley       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2025b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
2026b5da9499SMatthew G. Knepley         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2027b5da9499SMatthew G. Knepley       }
2028b5da9499SMatthew G. Knepley #endif
2029b5da9499SMatthew G. Knepley       supportNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
2030b5da9499SMatthew G. Knepley       supportNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
2031b5da9499SMatthew G. Knepley       supportNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
2032b5da9499SMatthew G. Knepley       supportNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
2033b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2034b5da9499SMatthew G. Knepley #if 1
2035b5da9499SMatthew G. Knepley       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2036b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
2037b5da9499SMatthew G. Knepley         if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportNew[p], fStartNew, fEndNew);
2038b5da9499SMatthew G. Knepley       }
2039b5da9499SMatthew G. Knepley #endif
2040b5da9499SMatthew G. Knepley     }
2041b5da9499SMatthew G. Knepley     /* Old vertices have identical supports */
2042b5da9499SMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
2043b5da9499SMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
2044b5da9499SMatthew G. Knepley       const PetscInt *support, *cone;
2045b5da9499SMatthew G. Knepley       PetscInt        size, s;
2046b5da9499SMatthew G. Knepley 
2047b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
2048b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
2049b5da9499SMatthew G. Knepley       for (s = 0; s < size; ++s) {
2050b5da9499SMatthew G. Knepley         PetscInt r = 0;
2051b5da9499SMatthew G. Knepley 
2052b5da9499SMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2053b5da9499SMatthew G. Knepley         if (cone[1] == v) r = 1;
2054b5da9499SMatthew G. Knepley         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
2055b5da9499SMatthew G. Knepley       }
2056b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2057b5da9499SMatthew G. Knepley #if 1
2058b5da9499SMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2059b5da9499SMatthew G. Knepley       for (p = 0; p < size; ++p) {
2060b5da9499SMatthew G. Knepley         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
2061b5da9499SMatthew G. Knepley       }
2062b5da9499SMatthew G. Knepley #endif
2063b5da9499SMatthew G. Knepley     }
2064b5da9499SMatthew G. Knepley     /* Edge vertices have 2 + face*2 + 0/1 supports */
2065b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
2066b5da9499SMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
2067b5da9499SMatthew G. Knepley       const PetscInt *cone, *support;
2068b5da9499SMatthew G. Knepley       PetscInt       *star = NULL, starSize, cellSize = 0, coneSize, size, s;
2069b5da9499SMatthew G. Knepley 
2070b5da9499SMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
2071b5da9499SMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
2072b5da9499SMatthew G. Knepley       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
2073b5da9499SMatthew G. Knepley       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
2074b5da9499SMatthew G. Knepley       for (s = 0; s < size; ++s) {
2075b5da9499SMatthew G. Knepley         PetscInt r = 0;
2076b5da9499SMatthew G. Knepley 
2077b5da9499SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2078b5da9499SMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2079b5da9499SMatthew G. Knepley         for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
2080b5da9499SMatthew G. Knepley         supportRef[2+s*2+0] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
2081b5da9499SMatthew G. Knepley         supportRef[2+s*2+1] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
2082b5da9499SMatthew G. Knepley       }
2083b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
2084b5da9499SMatthew G. Knepley       for (s = 0; s < starSize*2; s += 2) {
2085b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt;
2086b5da9499SMatthew G. Knepley         PetscInt        e01, e23;
2087b5da9499SMatthew G. Knepley 
2088b5da9499SMatthew G. Knepley         if ((star[s] >= cStart) && (star[s] < cEnd)) {
2089b5da9499SMatthew G. Knepley           /* Check edge 0-1 */
2090b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
2091b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
2092b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
209342525629SMatthew G. Knepley           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
2094b5da9499SMatthew G. Knepley           /* Check edge 2-3 */
2095b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
2096b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
209742525629SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
209842525629SMatthew G. Knepley           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
2099b5da9499SMatthew G. Knepley           if ((e01 == e) || (e23 == e)) {supportRef[2+size*2+cellSize++] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (star[s] - cStart);}
2100b5da9499SMatthew G. Knepley         }
2101b5da9499SMatthew G. Knepley       }
2102b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
2103b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2104b5da9499SMatthew G. Knepley #if 1
2105b5da9499SMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2106b5da9499SMatthew G. Knepley       for (p = 0; p < 2+size*2+cellSize; ++p) {
2107b5da9499SMatthew G. Knepley         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
2108b5da9499SMatthew G. Knepley       }
2109b5da9499SMatthew G. Knepley #endif
2110b5da9499SMatthew G. Knepley     }
2111b5da9499SMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
2112b5da9499SMatthew G. Knepley     ierr = DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);CHKERRQ(ierr);
2113b5da9499SMatthew G. Knepley     break;
21142eabf88fSMatthew G. Knepley   case 6:
21152eabf88fSMatthew G. Knepley     /* Hex 3D */
21162eabf88fSMatthew G. Knepley     /*
21172eabf88fSMatthew G. Knepley      Bottom (viewed from top)    Top
21182eabf88fSMatthew G. Knepley      1---------2---------2       7---------2---------6
21192eabf88fSMatthew G. Knepley      |         |         |       |         |         |
21202eabf88fSMatthew G. Knepley      |    B    2    C    |       |    H    2    G    |
21212eabf88fSMatthew G. Knepley      |         |         |       |         |         |
21222eabf88fSMatthew G. Knepley      3----3----0----1----1       3----3----0----1----1
21232eabf88fSMatthew G. Knepley      |         |         |       |         |         |
21242eabf88fSMatthew G. Knepley      |    A    0    D    |       |    E    0    F    |
21252eabf88fSMatthew G. Knepley      |         |         |       |         |         |
21262eabf88fSMatthew G. Knepley      0---------0---------3       4---------0---------5
21272eabf88fSMatthew G. Knepley      */
21282eabf88fSMatthew G. Knepley     /* All cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
21292eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
21302eabf88fSMatthew G. Knepley       const PetscInt  newp = (c - cStart)*8;
21312eabf88fSMatthew G. Knepley       const PetscInt *cone, *ornt;
21322eabf88fSMatthew G. Knepley       PetscInt        coneNew[6], orntNew[6];
21332eabf88fSMatthew G. Knepley 
21342eabf88fSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
21352eabf88fSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
21362eabf88fSMatthew G. Knepley       /* A hex */
2137e3f8b1d6SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
21382eabf88fSMatthew G. Knepley       orntNew[0] = ornt[0];
21392eabf88fSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
21402eabf88fSMatthew G. Knepley       orntNew[1] = 0;
2141e3f8b1d6SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
21422eabf88fSMatthew G. Knepley       orntNew[2] = ornt[2];
21432eabf88fSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
21442eabf88fSMatthew G. Knepley       orntNew[3] = 0;
21452eabf88fSMatthew G. Knepley       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
21462eabf88fSMatthew G. Knepley       orntNew[4] = 0;
2147e3f8b1d6SMatthew G. Knepley       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
21482eabf88fSMatthew G. Knepley       orntNew[5] = ornt[5];
21492eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
21502eabf88fSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
21512eabf88fSMatthew G. Knepley #if 1
21522eabf88fSMatthew G. Knepley       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
21532eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
21542eabf88fSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
21552eabf88fSMatthew G. Knepley       }
21562eabf88fSMatthew G. Knepley #endif
21572eabf88fSMatthew G. Knepley       /* B hex */
2158e3f8b1d6SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
21592eabf88fSMatthew G. Knepley       orntNew[0] = ornt[0];
21602eabf88fSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
21612eabf88fSMatthew G. Knepley       orntNew[1] = 0;
21622eabf88fSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
21632eabf88fSMatthew G. Knepley       orntNew[2] = -3;
2164e3f8b1d6SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
21652eabf88fSMatthew G. Knepley       orntNew[3] = ornt[3];
21662eabf88fSMatthew G. Knepley       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
21672eabf88fSMatthew G. Knepley       orntNew[4] = 0;
2168e3f8b1d6SMatthew G. Knepley       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
21692eabf88fSMatthew G. Knepley       orntNew[5] = ornt[5];
21702eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
21712eabf88fSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
21722eabf88fSMatthew G. Knepley #if 1
21732eabf88fSMatthew G. Knepley       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
21742eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
21752eabf88fSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
21762eabf88fSMatthew G. Knepley       }
21772eabf88fSMatthew G. Knepley #endif
21782eabf88fSMatthew G. Knepley       /* C hex */
2179e3f8b1d6SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
21802eabf88fSMatthew G. Knepley       orntNew[0] = ornt[0];
21812eabf88fSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
21822eabf88fSMatthew G. Knepley       orntNew[1] = 0;
21832eabf88fSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
21842eabf88fSMatthew G. Knepley       orntNew[2] = 0;
2185e3f8b1d6SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
21862eabf88fSMatthew G. Knepley       orntNew[3] = ornt[3];
2187e3f8b1d6SMatthew G. Knepley       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
21882eabf88fSMatthew G. Knepley       orntNew[4] = ornt[4];
21892eabf88fSMatthew G. Knepley       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
21902eabf88fSMatthew G. Knepley       orntNew[5] = -3;
21912eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
21922eabf88fSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
21932eabf88fSMatthew G. Knepley #if 1
21942eabf88fSMatthew G. Knepley       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
21952eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
21962eabf88fSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
21972eabf88fSMatthew G. Knepley       }
21982eabf88fSMatthew G. Knepley #endif
21992eabf88fSMatthew G. Knepley       /* D hex */
2200e3f8b1d6SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
22012eabf88fSMatthew G. Knepley       orntNew[0] = ornt[0];
22022eabf88fSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
22032eabf88fSMatthew G. Knepley       orntNew[1] = 0;
2204e3f8b1d6SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
22052eabf88fSMatthew G. Knepley       orntNew[2] = ornt[2];
22062eabf88fSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
22072eabf88fSMatthew G. Knepley       orntNew[3] = -3;
2208e3f8b1d6SMatthew G. Knepley       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
22092eabf88fSMatthew G. Knepley       orntNew[4] = ornt[4];
22102eabf88fSMatthew G. Knepley       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
22112eabf88fSMatthew G. Knepley       orntNew[5] = -3;
22122eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
22132eabf88fSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
22142eabf88fSMatthew G. Knepley #if 1
22152eabf88fSMatthew G. Knepley       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
22162eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
22172eabf88fSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
22182eabf88fSMatthew G. Knepley       }
22192eabf88fSMatthew G. Knepley #endif
22202eabf88fSMatthew G. Knepley       /* E hex */
22212eabf88fSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
22222eabf88fSMatthew G. Knepley       orntNew[0] = -3;
2223e3f8b1d6SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
22242eabf88fSMatthew G. Knepley       orntNew[1] = ornt[1];
2225e3f8b1d6SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
22262eabf88fSMatthew G. Knepley       orntNew[2] = ornt[2];
22272eabf88fSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
22282eabf88fSMatthew G. Knepley       orntNew[3] = 0;
22292eabf88fSMatthew G. Knepley       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
22302eabf88fSMatthew G. Knepley       orntNew[4] = 0;
2231e3f8b1d6SMatthew G. Knepley       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
22322eabf88fSMatthew G. Knepley       orntNew[5] = ornt[5];
2233b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
2234b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
22352eabf88fSMatthew G. Knepley #if 1
2236b164cbf2SMatthew G. Knepley       if ((newp+4 < cStartNew) || (newp+4 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+4, cStartNew, cEndNew);
22372eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
22382eabf88fSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
22392eabf88fSMatthew G. Knepley       }
22402eabf88fSMatthew G. Knepley #endif
22412eabf88fSMatthew G. Knepley       /* F hex */
22422eabf88fSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
22432eabf88fSMatthew G. Knepley       orntNew[0] = -3;
2244e3f8b1d6SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
22452eabf88fSMatthew G. Knepley       orntNew[1] = ornt[1];
2246e3f8b1d6SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
22472eabf88fSMatthew G. Knepley       orntNew[2] = ornt[2];
22482eabf88fSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
22492eabf88fSMatthew G. Knepley       orntNew[3] = 0;
2250e3f8b1d6SMatthew G. Knepley       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
22512eabf88fSMatthew G. Knepley       orntNew[4] = ornt[4];
22522eabf88fSMatthew G. Knepley       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
22532eabf88fSMatthew G. Knepley       orntNew[5] = -3;
2254b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
2255b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
22562eabf88fSMatthew G. Knepley #if 1
2257b164cbf2SMatthew G. Knepley       if ((newp+5 < cStartNew) || (newp+5 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+5, cStartNew, cEndNew);
22582eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
22592eabf88fSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
22602eabf88fSMatthew G. Knepley       }
22612eabf88fSMatthew G. Knepley #endif
22622eabf88fSMatthew G. Knepley       /* G hex */
22632eabf88fSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
22642eabf88fSMatthew G. Knepley       orntNew[0] = -3;
2265e3f8b1d6SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
22662eabf88fSMatthew G. Knepley       orntNew[1] = ornt[1];
22672eabf88fSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
22682eabf88fSMatthew G. Knepley       orntNew[2] = -3;
2269e3f8b1d6SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
22702eabf88fSMatthew G. Knepley       orntNew[3] = ornt[3];
2271e3f8b1d6SMatthew G. Knepley       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
22722eabf88fSMatthew G. Knepley       orntNew[4] = ornt[4];
22732eabf88fSMatthew G. Knepley       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
22742eabf88fSMatthew G. Knepley       orntNew[5] = 0;
2275b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
2276b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
22772eabf88fSMatthew G. Knepley #if 1
2278b164cbf2SMatthew G. Knepley       if ((newp+6 < cStartNew) || (newp+6 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+6, cStartNew, cEndNew);
22792eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
22802eabf88fSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
22812eabf88fSMatthew G. Knepley       }
22822eabf88fSMatthew G. Knepley #endif
22832eabf88fSMatthew G. Knepley       /* H hex */
22842eabf88fSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
22852eabf88fSMatthew G. Knepley       orntNew[0] = -3;
2286e3f8b1d6SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
22872eabf88fSMatthew G. Knepley       orntNew[1] = ornt[1];
22882eabf88fSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
22892eabf88fSMatthew G. Knepley       orntNew[2] = -3;
2290e3f8b1d6SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
22912eabf88fSMatthew G. Knepley       orntNew[3] = ornt[3];
22922eabf88fSMatthew G. Knepley       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
22932eabf88fSMatthew G. Knepley       orntNew[4] = -3;
2294e3f8b1d6SMatthew G. Knepley       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
22952eabf88fSMatthew G. Knepley       orntNew[5] = ornt[5];
2296b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
2297b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
22982eabf88fSMatthew G. Knepley #if 1
2299b164cbf2SMatthew G. Knepley       if ((newp+7 < cStartNew) || (newp+7 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+7, cStartNew, cEndNew);
23002eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
23012eabf88fSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
23022eabf88fSMatthew G. Knepley       }
23032eabf88fSMatthew G. Knepley #endif
23042eabf88fSMatthew G. Knepley     }
23052eabf88fSMatthew G. Knepley     /* Split faces have 4 edges and the same cells as the parent */
23062eabf88fSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
23072eabf88fSMatthew G. Knepley     ierr = PetscMalloc((4 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
23082eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
23092eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
2310aaebbb9dSMatthew G. Knepley         /* TODO: This can come from GetFaces_Internal() */
23112eabf88fSMatthew G. Knepley         const PetscInt  newCells[24] = {0, 1, 2, 3,  4, 5, 6, 7,  0, 3, 5, 4,  2, 1, 7, 6,  3, 2, 6, 5,  0, 4, 7, 1};
23122eabf88fSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*4 + r;
23132eabf88fSMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
2314aaebbb9dSMatthew G. Knepley         PetscInt        coneNew[4], orntNew[4], coneSize, c, supportSize, s;
23152eabf88fSMatthew G. Knepley 
23162eabf88fSMatthew G. Knepley         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
2317aaebbb9dSMatthew G. Knepley         ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
2318aaebbb9dSMatthew G. Knepley         coneNew[0] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
2319aaebbb9dSMatthew G. Knepley         orntNew[0] = ornt[(r+3)%4];
2320aaebbb9dSMatthew G. Knepley         coneNew[1] = eStartNew + (cone[r]       - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
2321aaebbb9dSMatthew G. Knepley         orntNew[1] = ornt[r];
23222eabf88fSMatthew G. Knepley         coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
2323aaebbb9dSMatthew G. Knepley         orntNew[2] = 0;
23242eabf88fSMatthew G. Knepley         coneNew[3] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + (r+3)%4;
2325aaebbb9dSMatthew G. Knepley         orntNew[3] = -2;
23262eabf88fSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2327aaebbb9dSMatthew G. Knepley         ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
23282eabf88fSMatthew G. Knepley #if 1
23292eabf88fSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
23302eabf88fSMatthew G. Knepley         for (p = 0; p < 4; ++p) {
23312eabf88fSMatthew G. Knepley           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
23322eabf88fSMatthew G. Knepley         }
23332eabf88fSMatthew G. Knepley #endif
23342eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
23352eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
23362eabf88fSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
23372eabf88fSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
23382eabf88fSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
23392eabf88fSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
23402eabf88fSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
23412eabf88fSMatthew G. Knepley             if (cone[c] == f) break;
23422eabf88fSMatthew G. Knepley           }
2343a3f78057SMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+GetQuadSubface_Static(ornt[c], r)];
23442eabf88fSMatthew G. Knepley         }
23452eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
23462eabf88fSMatthew G. Knepley #if 1
23472eabf88fSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
23482eabf88fSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
23492eabf88fSMatthew G. Knepley           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
23502eabf88fSMatthew G. Knepley         }
23512eabf88fSMatthew G. Knepley #endif
23522eabf88fSMatthew G. Knepley       }
23532eabf88fSMatthew G. Knepley     }
23542eabf88fSMatthew G. Knepley     /* Interior faces have 4 edges and 2 cells */
23552eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
23562eabf88fSMatthew G. Knepley       const PetscInt  newCells[24] = {0, 3,  2, 3,  1, 2,  0, 1,  4, 5,  5, 6,  6, 7,  4, 7,  0, 4,  3, 5,  2, 6,  1, 7};
2357afb2665bSMatthew G. Knepley       const PetscInt *cone, *ornt;
2358afb2665bSMatthew G. Knepley       PetscInt        newp, coneNew[4], orntNew[4], supportNew[2];
23592eabf88fSMatthew G. Knepley 
23602eabf88fSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2361afb2665bSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2362afb2665bSMatthew G. Knepley       /* A-D face */
2363afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0;
2364afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
2365afb2665bSMatthew G. Knepley       orntNew[0] = -2;
2366afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
2367afb2665bSMatthew G. Knepley       orntNew[1] = 0;
2368afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
2369afb2665bSMatthew G. Knepley       orntNew[2] = 0;
2370afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
2371afb2665bSMatthew G. Knepley       orntNew[3] = -2;
23722eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2373afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
23742eabf88fSMatthew G. Knepley #if 1
23752eabf88fSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
23762eabf88fSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
23772eabf88fSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
23782eabf88fSMatthew G. Knepley       }
23792eabf88fSMatthew G. Knepley #endif
2380afb2665bSMatthew G. Knepley       /* C-D face */
2381afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1;
2382afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
2383afb2665bSMatthew G. Knepley       orntNew[0] = -2;
2384afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
2385afb2665bSMatthew G. Knepley       orntNew[1] = 0;
2386afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
2387afb2665bSMatthew G. Knepley       orntNew[2] = 0;
2388afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
2389afb2665bSMatthew G. Knepley       orntNew[3] = -2;
2390afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2391afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2392afb2665bSMatthew G. Knepley #if 1
2393afb2665bSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2394afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
2395afb2665bSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2396afb2665bSMatthew G. Knepley       }
2397afb2665bSMatthew G. Knepley #endif
2398afb2665bSMatthew G. Knepley       /* B-C face */
2399afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2;
2400afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
2401afb2665bSMatthew G. Knepley       orntNew[0] = -2;
2402afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
2403afb2665bSMatthew G. Knepley       orntNew[1] = 0;
2404afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
2405afb2665bSMatthew G. Knepley       orntNew[2] = 0;
2406afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
2407afb2665bSMatthew G. Knepley       orntNew[3] = -2;
2408afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2409afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2410afb2665bSMatthew G. Knepley #if 1
2411afb2665bSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2412afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
2413afb2665bSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2414afb2665bSMatthew G. Knepley       }
2415afb2665bSMatthew G. Knepley #endif
2416afb2665bSMatthew G. Knepley       /* A-B face */
2417afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3;
2418afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
2419afb2665bSMatthew G. Knepley       orntNew[0] = -2;
2420afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
2421afb2665bSMatthew G. Knepley       orntNew[1] = 0;
2422afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
2423afb2665bSMatthew G. Knepley       orntNew[2] = 0;
2424afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
2425afb2665bSMatthew G. Knepley       orntNew[3] = -2;
2426afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2427afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2428afb2665bSMatthew G. Knepley #if 1
2429afb2665bSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2430afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
2431afb2665bSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2432afb2665bSMatthew G. Knepley       }
2433afb2665bSMatthew G. Knepley #endif
2434afb2665bSMatthew G. Knepley       /* E-F face */
2435afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4;
2436afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
2437afb2665bSMatthew G. Knepley       orntNew[0] = -2;
2438afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
2439afb2665bSMatthew G. Knepley       orntNew[1] = 0;
2440afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
2441afb2665bSMatthew G. Knepley       orntNew[2] = 0;
2442afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
2443afb2665bSMatthew G. Knepley       orntNew[3] = -2;
2444afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2445afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2446afb2665bSMatthew G. Knepley #if 1
2447afb2665bSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2448afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
2449afb2665bSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2450afb2665bSMatthew G. Knepley       }
2451afb2665bSMatthew G. Knepley #endif
2452afb2665bSMatthew G. Knepley       /* F-G face */
2453afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5;
2454afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
2455afb2665bSMatthew G. Knepley       orntNew[0] = -2;
2456afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
2457afb2665bSMatthew G. Knepley       orntNew[1] = 0;
2458afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
2459afb2665bSMatthew G. Knepley       orntNew[2] = 0;
2460afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
2461afb2665bSMatthew G. Knepley       orntNew[3] = -2;
2462afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2463afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2464afb2665bSMatthew G. Knepley #if 1
2465afb2665bSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2466afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
2467afb2665bSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2468afb2665bSMatthew G. Knepley       }
2469afb2665bSMatthew G. Knepley #endif
2470afb2665bSMatthew G. Knepley       /* G-H face */
2471afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6;
2472afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
2473afb2665bSMatthew G. Knepley       orntNew[0] = -2;
2474afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
2475afb2665bSMatthew G. Knepley       orntNew[1] = 0;
2476afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
2477afb2665bSMatthew G. Knepley       orntNew[2] = 0;
2478afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
2479afb2665bSMatthew G. Knepley       orntNew[3] = -2;
2480afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2481afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2482afb2665bSMatthew G. Knepley #if 1
2483afb2665bSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2484afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
2485afb2665bSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2486afb2665bSMatthew G. Knepley       }
2487afb2665bSMatthew G. Knepley #endif
2488afb2665bSMatthew G. Knepley       /* E-H face */
2489afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7;
2490afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
2491afb2665bSMatthew G. Knepley       orntNew[0] = -2;
2492afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
2493afb2665bSMatthew G. Knepley       orntNew[1] = 0;
2494afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
2495afb2665bSMatthew G. Knepley       orntNew[2] = 0;
2496afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
2497afb2665bSMatthew G. Knepley       orntNew[3] = -2;
2498afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2499afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2500afb2665bSMatthew G. Knepley #if 1
2501afb2665bSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2502afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
2503afb2665bSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2504afb2665bSMatthew G. Knepley       }
2505afb2665bSMatthew G. Knepley #endif
2506afb2665bSMatthew G. Knepley       /* A-E face */
2507afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8;
2508afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
2509afb2665bSMatthew G. Knepley       orntNew[0] = -2;
2510afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
2511afb2665bSMatthew G. Knepley       orntNew[1] = 0;
2512afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
2513afb2665bSMatthew G. Knepley       orntNew[2] = 0;
2514afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
2515afb2665bSMatthew G. Knepley       orntNew[3] = -2;
2516afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2517afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2518afb2665bSMatthew G. Knepley #if 1
2519afb2665bSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2520afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
2521afb2665bSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2522afb2665bSMatthew G. Knepley       }
2523afb2665bSMatthew G. Knepley #endif
2524afb2665bSMatthew G. Knepley       /* D-F face */
2525afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9;
2526afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
2527afb2665bSMatthew G. Knepley       orntNew[0] = -2;
2528afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
2529afb2665bSMatthew G. Knepley       orntNew[1] = 0;
2530afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
2531afb2665bSMatthew G. Knepley       orntNew[2] = 0;
2532afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
2533afb2665bSMatthew G. Knepley       orntNew[3] = -2;
2534afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2535afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2536afb2665bSMatthew G. Knepley #if 1
2537afb2665bSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2538afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
2539afb2665bSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2540afb2665bSMatthew G. Knepley       }
2541afb2665bSMatthew G. Knepley #endif
2542afb2665bSMatthew G. Knepley       /* C-G face */
2543afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10;
2544afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
2545afb2665bSMatthew G. Knepley       orntNew[0] = -2;
2546afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
2547afb2665bSMatthew G. Knepley       orntNew[1] = 0;
2548afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
2549afb2665bSMatthew G. Knepley       orntNew[2] = 0;
2550afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
2551afb2665bSMatthew G. Knepley       orntNew[3] = -2;
2552afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2553afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2554afb2665bSMatthew G. Knepley #if 1
2555afb2665bSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2556afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
2557afb2665bSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2558afb2665bSMatthew G. Knepley       }
2559afb2665bSMatthew G. Knepley #endif
2560afb2665bSMatthew G. Knepley       /* B-H face */
2561afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11;
2562afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
2563afb2665bSMatthew G. Knepley       orntNew[0] = -2;
2564afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
2565afb2665bSMatthew G. Knepley       orntNew[1] = 0;
2566afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
2567afb2665bSMatthew G. Knepley       orntNew[2] = 0;
2568afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
2569afb2665bSMatthew G. Knepley       orntNew[3] = -2;
2570afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2571afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2572afb2665bSMatthew G. Knepley #if 1
2573afb2665bSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2574afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
2575afb2665bSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2576afb2665bSMatthew G. Knepley       }
2577afb2665bSMatthew G. Knepley #endif
2578afb2665bSMatthew G. Knepley       for (r = 0; r < 12; ++r) {
2579afb2665bSMatthew G. Knepley         newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
25802eabf88fSMatthew G. Knepley         supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
25812eabf88fSMatthew G. Knepley         supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
25822eabf88fSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
25832eabf88fSMatthew G. Knepley #if 1
25842eabf88fSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
25852eabf88fSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
25862eabf88fSMatthew G. Knepley           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
25872eabf88fSMatthew G. Knepley         }
25882eabf88fSMatthew G. Knepley #endif
25892eabf88fSMatthew G. Knepley       }
25902eabf88fSMatthew G. Knepley     }
25912eabf88fSMatthew G. Knepley     /* Split edges have 2 vertices and the same faces as the parent */
25922eabf88fSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
25932eabf88fSMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
25942eabf88fSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
25952eabf88fSMatthew G. Knepley 
25962eabf88fSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
25972eabf88fSMatthew G. Knepley         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
25982eabf88fSMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
25992eabf88fSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
26002eabf88fSMatthew G. Knepley 
26012eabf88fSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
26022eabf88fSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
26032eabf88fSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
26042eabf88fSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
26052eabf88fSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
26062eabf88fSMatthew G. Knepley #if 1
26072eabf88fSMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
26082eabf88fSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
26092eabf88fSMatthew G. Knepley           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
26102eabf88fSMatthew G. Knepley         }
26112eabf88fSMatthew G. Knepley #endif
26122eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
26132eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
26142eabf88fSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
26152eabf88fSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
26162eabf88fSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
26172eabf88fSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
26182eabf88fSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
26192eabf88fSMatthew G. Knepley             if (cone[c] == e) break;
26202eabf88fSMatthew G. Knepley           }
26212eabf88fSMatthew G. Knepley           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
26222eabf88fSMatthew G. Knepley         }
26232eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
26242eabf88fSMatthew G. Knepley #if 1
26252eabf88fSMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
26262eabf88fSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
26272eabf88fSMatthew G. Knepley           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
26282eabf88fSMatthew G. Knepley         }
26292eabf88fSMatthew G. Knepley #endif
26302eabf88fSMatthew G. Knepley       }
26312eabf88fSMatthew G. Knepley     }
26322eabf88fSMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells faces */
26332eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
26346b852384SMatthew G. Knepley       const PetscInt  newFaces[24] = {3, 2, 1, 0,  4, 5, 6, 7,  0, 9, 4, 8,  2, 11, 6, 10,  1, 10, 5, 9,  8, 7, 11, 3};
26352eabf88fSMatthew G. Knepley       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
26366b852384SMatthew G. Knepley       const PetscInt *cone, *coneCell, *orntCell, *support;
26372eabf88fSMatthew G. Knepley       PetscInt        coneNew[2], coneSize, c, supportSize, s;
26382eabf88fSMatthew G. Knepley 
26392eabf88fSMatthew G. Knepley       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
26402eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
26412eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
26422eabf88fSMatthew G. Knepley 
26432eabf88fSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
26442eabf88fSMatthew G. Knepley         coneNew[1] = newv;
26452eabf88fSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
26462eabf88fSMatthew G. Knepley #if 1
26472eabf88fSMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
26482eabf88fSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
26492eabf88fSMatthew G. Knepley           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
26502eabf88fSMatthew G. Knepley         }
26512eabf88fSMatthew G. Knepley #endif
26522eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
26532eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
26542eabf88fSMatthew G. Knepley         supportRef[0] = fStartNew + (f - fStart)*4 + r;
26552eabf88fSMatthew G. Knepley         supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
26562eabf88fSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
26576b852384SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
26586b852384SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &coneCell);CHKERRQ(ierr);
26596b852384SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &orntCell);CHKERRQ(ierr);
26602eabf88fSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
26616b852384SMatthew G. Knepley           supportRef[2+s] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdge_Static(orntCell[c], r)];
26622eabf88fSMatthew G. Knepley         }
26632eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
26642eabf88fSMatthew G. Knepley #if 1
26652eabf88fSMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
26662eabf88fSMatthew G. Knepley         for (p = 0; p < 2+supportSize; ++p) {
26672eabf88fSMatthew G. Knepley           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
26682eabf88fSMatthew G. Knepley         }
26692eabf88fSMatthew G. Knepley #endif
26702eabf88fSMatthew G. Knepley       }
26712eabf88fSMatthew G. Knepley     }
26722eabf88fSMatthew G. Knepley     /* Cell edges have 2 vertices and 4 faces */
26732eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
26742eabf88fSMatthew G. Knepley       const PetscInt  newFaces[24] = {0, 1, 2, 3,  4, 5, 6, 7,  0, 9, 4, 8,  2, 11, 6, 10,  1, 10, 5, 9,  3, 8, 7, 11};
26752eabf88fSMatthew G. Knepley       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
26762eabf88fSMatthew G. Knepley       const PetscInt *cone;
26772eabf88fSMatthew G. Knepley       PetscInt        coneNew[2], supportNew[4];
26782eabf88fSMatthew G. Knepley 
26792eabf88fSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
26802eabf88fSMatthew G. Knepley       for (r = 0; r < 6; ++r) {
26812eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
26822eabf88fSMatthew G. Knepley 
26832eabf88fSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
26842eabf88fSMatthew G. Knepley         coneNew[1] = newv;
26852eabf88fSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
26862eabf88fSMatthew G. Knepley #if 1
26872eabf88fSMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
26882eabf88fSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
26892eabf88fSMatthew G. Knepley           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
26902eabf88fSMatthew G. Knepley         }
26912eabf88fSMatthew G. Knepley #endif
26922eabf88fSMatthew G. Knepley         for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
26932eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
26942eabf88fSMatthew G. Knepley #if 1
26952eabf88fSMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
26962eabf88fSMatthew G. Knepley         for (p = 0; p < 4; ++p) {
26972eabf88fSMatthew G. Knepley           if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportNew[p], fStartNew, fEndNew);
26982eabf88fSMatthew G. Knepley         }
26992eabf88fSMatthew G. Knepley #endif
27002eabf88fSMatthew G. Knepley       }
27012eabf88fSMatthew G. Knepley     }
27022eabf88fSMatthew G. Knepley     /* Old vertices have identical supports */
27032eabf88fSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
27042eabf88fSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
27052eabf88fSMatthew G. Knepley       const PetscInt *support, *cone;
27062eabf88fSMatthew G. Knepley       PetscInt        size, s;
27072eabf88fSMatthew G. Knepley 
27082eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
27092eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
27102eabf88fSMatthew G. Knepley       for (s = 0; s < size; ++s) {
27112eabf88fSMatthew G. Knepley         PetscInt r = 0;
27122eabf88fSMatthew G. Knepley 
27132eabf88fSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
27142eabf88fSMatthew G. Knepley         if (cone[1] == v) r = 1;
27152eabf88fSMatthew G. Knepley         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
27162eabf88fSMatthew G. Knepley       }
27172eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
27182eabf88fSMatthew G. Knepley #if 1
27192eabf88fSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
27202eabf88fSMatthew G. Knepley       for (p = 0; p < size; ++p) {
27212eabf88fSMatthew G. Knepley         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
27222eabf88fSMatthew G. Knepley       }
27232eabf88fSMatthew G. Knepley #endif
27242eabf88fSMatthew G. Knepley     }
27252eabf88fSMatthew G. Knepley     /* Edge vertices have 2 + faces supports */
27262eabf88fSMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
27272eabf88fSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
27282eabf88fSMatthew G. Knepley       const PetscInt *cone, *support;
27292eabf88fSMatthew G. Knepley       PetscInt        size, s;
27302eabf88fSMatthew G. Knepley 
27312eabf88fSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
27322eabf88fSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
27332eabf88fSMatthew G. Knepley       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
27342eabf88fSMatthew G. Knepley       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
27352eabf88fSMatthew G. Knepley       for (s = 0; s < size; ++s) {
27362eabf88fSMatthew G. Knepley         PetscInt r;
27372eabf88fSMatthew G. Knepley 
27382eabf88fSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2739a660e16cSMatthew G. Knepley         for (r = 0; r < 4; ++r) if (cone[r] == e) break;
27402eabf88fSMatthew G. Knepley         supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*4 + r;
27412eabf88fSMatthew G. Knepley       }
27422eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
27432eabf88fSMatthew G. Knepley #if 1
27442eabf88fSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
27452eabf88fSMatthew G. Knepley       for (p = 0; p < 2+size; ++p) {
27462eabf88fSMatthew G. Knepley         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
27472eabf88fSMatthew G. Knepley       }
27482eabf88fSMatthew G. Knepley #endif
27492eabf88fSMatthew G. Knepley     }
27502eabf88fSMatthew G. Knepley     /* Face vertices have 4 + cells supports */
27512eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
27522eabf88fSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
27532eabf88fSMatthew G. Knepley       const PetscInt *cone, *support;
27542eabf88fSMatthew G. Knepley       PetscInt        size, s;
27552eabf88fSMatthew G. Knepley 
27562eabf88fSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
27572eabf88fSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
27582eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (e - eStart)*2 +  (f - fStart)*4 + r;
27592eabf88fSMatthew G. Knepley       for (s = 0; s < size; ++s) {
27602eabf88fSMatthew G. Knepley         PetscInt r;
27612eabf88fSMatthew G. Knepley 
27622eabf88fSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
27632eabf88fSMatthew G. Knepley         for (r = 0; r < 6; ++r) if (cone[r] == f) break;
27642eabf88fSMatthew G. Knepley         supportRef[4+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (support[s] - cStart)*6 + r;
27652eabf88fSMatthew G. Knepley       }
27662eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
27672eabf88fSMatthew G. Knepley #if 1
27682eabf88fSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
27692eabf88fSMatthew G. Knepley       for (p = 0; p < 4+size; ++p) {
27702eabf88fSMatthew G. Knepley         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
27712eabf88fSMatthew G. Knepley       }
27722eabf88fSMatthew G. Knepley #endif
27732eabf88fSMatthew G. Knepley     }
27742eabf88fSMatthew G. Knepley     /* Cell vertices have 6 supports */
27752eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
27762eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
27772eabf88fSMatthew G. Knepley       PetscInt       supportNew[6];
27782eabf88fSMatthew G. Knepley 
27792eabf88fSMatthew G. Knepley       for (r = 0; r < 6; ++r) {
27802eabf88fSMatthew G. Knepley         supportNew[r] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
27812eabf88fSMatthew G. Knepley       }
27822eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
27832eabf88fSMatthew G. Knepley     }
2784da00770fSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
27852eabf88fSMatthew G. Knepley     break;
278675d3a19aSMatthew G. Knepley   default:
278775d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
278875d3a19aSMatthew G. Knepley   }
278975d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
279075d3a19aSMatthew G. Knepley }
279175d3a19aSMatthew G. Knepley 
279275d3a19aSMatthew G. Knepley #undef __FUNCT__
279375d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetCoordinates"
279475d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
279575d3a19aSMatthew G. Knepley {
279675d3a19aSMatthew G. Knepley   PetscSection   coordSection, coordSectionNew;
279775d3a19aSMatthew G. Knepley   Vec            coordinates, coordinatesNew;
279875d3a19aSMatthew G. Knepley   PetscScalar   *coords, *coordsNew;
2799b5da9499SMatthew G. Knepley   PetscInt       dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, eStart, eEnd, eMax, e, fStart, fEnd, fMax, f;
280075d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
280175d3a19aSMatthew G. Knepley 
280275d3a19aSMatthew G. Knepley   PetscFunctionBegin;
280375d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
280475d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
280575d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
2806b5da9499SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
280775d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
280875d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
2809b5da9499SMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, &eMax, NULL);CHKERRQ(ierr);
281075d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr);
281175d3a19aSMatthew G. Knepley   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
281275d3a19aSMatthew G. Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr);
281375d3a19aSMatthew G. Knepley   ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr);
281475d3a19aSMatthew G. Knepley   ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr);
281575d3a19aSMatthew G. Knepley   ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr);
281675d3a19aSMatthew G. Knepley   if (fMax < 0) fMax = fEnd;
2817b5da9499SMatthew G. Knepley   if (eMax < 0) eMax = eEnd;
281875d3a19aSMatthew G. Knepley   /* All vertices have the dim coordinates */
281975d3a19aSMatthew G. Knepley   for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) {
282075d3a19aSMatthew G. Knepley     ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr);
282175d3a19aSMatthew G. Knepley     ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr);
282275d3a19aSMatthew G. Knepley   }
282375d3a19aSMatthew G. Knepley   ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr);
282475d3a19aSMatthew G. Knepley   ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr);
282575d3a19aSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
282675d3a19aSMatthew G. Knepley   ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr);
282775d3a19aSMatthew G. Knepley   ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr);
282875d3a19aSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr);
282975d3a19aSMatthew G. Knepley   ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr);
283075d3a19aSMatthew G. Knepley   ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr);
283175d3a19aSMatthew G. Knepley   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
283275d3a19aSMatthew G. Knepley   ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
2833b5da9499SMatthew G. Knepley   switch (refiner) {
2834b5da9499SMatthew G. Knepley   case 6: /* Hex 3D */
2835b5da9499SMatthew G. Knepley     /* Face vertices have the average of corner coordinates */
2836b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
2837c91acedaSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
2838b5da9499SMatthew G. Knepley       PetscInt      *cone = NULL;
2839b5da9499SMatthew G. Knepley       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;
2840b5da9499SMatthew G. Knepley 
2841b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
2842b5da9499SMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
2843b5da9499SMatthew G. Knepley         const PetscInt point = cone[p];
2844b5da9499SMatthew G. Knepley         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
2845b5da9499SMatthew G. Knepley       }
2846b5da9499SMatthew G. Knepley       for (v = 0; v < coneSize; ++v) {
2847b5da9499SMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[v], &off[v]);CHKERRQ(ierr);
2848b5da9499SMatthew G. Knepley       }
2849b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
2850b5da9499SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
2851b5da9499SMatthew G. Knepley         coordsNew[offnew+d] = 0.0;
2852b5da9499SMatthew G. Knepley         for (v = 0; v < coneSize; ++v) coordsNew[offnew+d] += coords[off[v]+d];
2853b5da9499SMatthew G. Knepley         coordsNew[offnew+d] /= coneSize;
2854b5da9499SMatthew G. Knepley       }
2855b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
2856b5da9499SMatthew G. Knepley     }
2857b5da9499SMatthew G. Knepley   case 2: /* Hex 2D */
2858b5da9499SMatthew G. Knepley     /* Cell vertices have the average of corner coordinates */
2859b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
2860c91acedaSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (c - cStart) + (dim > 2 ? (fEnd - fStart) : 0);
2861b5da9499SMatthew G. Knepley       PetscInt      *cone = NULL;
2862b5da9499SMatthew G. Knepley       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;
2863b5da9499SMatthew G. Knepley 
2864b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
2865b5da9499SMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
2866b5da9499SMatthew G. Knepley         const PetscInt point = cone[p];
2867b5da9499SMatthew G. Knepley         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
2868b5da9499SMatthew G. Knepley       }
2869b5da9499SMatthew G. Knepley       for (v = 0; v < coneSize; ++v) {
2870b5da9499SMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[v], &off[v]);CHKERRQ(ierr);
2871b5da9499SMatthew G. Knepley       }
2872b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
2873b5da9499SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
2874b5da9499SMatthew G. Knepley         coordsNew[offnew+d] = 0.0;
2875b5da9499SMatthew G. Knepley         for (v = 0; v < coneSize; ++v) coordsNew[offnew+d] += coords[off[v]+d];
2876b5da9499SMatthew G. Knepley         coordsNew[offnew+d] /= coneSize;
2877b5da9499SMatthew G. Knepley       }
2878b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
2879b5da9499SMatthew G. Knepley     }
2880b5da9499SMatthew G. Knepley   case 1: /* Simplicial 2D */
2881b5da9499SMatthew G. Knepley   case 3: /* Hybrid Simplicial 2D */
2882b5da9499SMatthew G. Knepley   case 5: /* Simplicial 3D */
2883b5da9499SMatthew G. Knepley     /* Edge vertices have the average of endpoint coordinates */
2884b5da9499SMatthew G. Knepley     for (e = eStart; e < eMax; ++e) {
2885b5da9499SMatthew G. Knepley       const PetscInt  newv = vStartNew + (vEnd - vStart) + (e - eStart);
2886b5da9499SMatthew G. Knepley       const PetscInt *cone;
2887b5da9499SMatthew G. Knepley       PetscInt        coneSize, offA, offB, offnew, d;
2888b5da9499SMatthew G. Knepley 
2889b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr);
2890b5da9499SMatthew G. Knepley       if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize);
2891b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
2892b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
2893b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
2894b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
2895b5da9499SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
2896b5da9499SMatthew G. Knepley         coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]);
2897b5da9499SMatthew G. Knepley       }
2898b5da9499SMatthew G. Knepley     }
289975d3a19aSMatthew G. Knepley     /* Old vertices have the same coordinates */
290075d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
290175d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (v - vStart);
290275d3a19aSMatthew G. Knepley       PetscInt       off, offnew, d;
290375d3a19aSMatthew G. Knepley 
290475d3a19aSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
290575d3a19aSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
290675d3a19aSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
290775d3a19aSMatthew G. Knepley         coordsNew[offnew+d] = coords[off+d];
290875d3a19aSMatthew G. Knepley       }
290975d3a19aSMatthew G. Knepley     }
2910b5da9499SMatthew G. Knepley     break;
2911b5da9499SMatthew G. Knepley   default:
2912b5da9499SMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
291375d3a19aSMatthew G. Knepley   }
291475d3a19aSMatthew G. Knepley   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
291575d3a19aSMatthew G. Knepley   ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
291675d3a19aSMatthew G. Knepley   ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr);
291775d3a19aSMatthew G. Knepley   ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr);
291875d3a19aSMatthew G. Knepley   ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr);
291975d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
292075d3a19aSMatthew G. Knepley }
292175d3a19aSMatthew G. Knepley 
292275d3a19aSMatthew G. Knepley #undef __FUNCT__
292375d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexCreateProcessSF"
292475d3a19aSMatthew G. Knepley PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
292575d3a19aSMatthew G. Knepley {
292675d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, l;
292775d3a19aSMatthew G. Knepley   const PetscInt    *localPoints;
292875d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
292975d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
293075d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
293175d3a19aSMatthew G. Knepley   PetscInt          *ranks, *ranksNew;
293275d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
293375d3a19aSMatthew G. Knepley 
293475d3a19aSMatthew G. Knepley   PetscFunctionBegin;
293575d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
293675d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr);
293775d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
293875d3a19aSMatthew G. Knepley     ranks[l] = remotePoints[l].rank;
293975d3a19aSMatthew G. Knepley   }
294075d3a19aSMatthew G. Knepley   ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr);
294175d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt),    &ranksNew);CHKERRQ(ierr);
294275d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt),    &localPointsNew);CHKERRQ(ierr);
294375d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr);
294475d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
294575d3a19aSMatthew G. Knepley     ranksNew[l]              = ranks[l];
294675d3a19aSMatthew G. Knepley     localPointsNew[l]        = l;
294775d3a19aSMatthew G. Knepley     remotePointsNew[l].index = 0;
294875d3a19aSMatthew G. Knepley     remotePointsNew[l].rank  = ranksNew[l];
294975d3a19aSMatthew G. Knepley   }
295075d3a19aSMatthew G. Knepley   ierr = PetscFree(ranks);CHKERRQ(ierr);
295175d3a19aSMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);
295275d3a19aSMatthew G. Knepley   ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr);
295375d3a19aSMatthew G. Knepley   ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr);
295475d3a19aSMatthew G. Knepley   ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
295575d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
295675d3a19aSMatthew G. Knepley }
295775d3a19aSMatthew G. Knepley 
295875d3a19aSMatthew G. Knepley #undef __FUNCT__
295975d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerCreateSF"
296075d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
296175d3a19aSMatthew G. Knepley {
296275d3a19aSMatthew G. Knepley   PetscSF            sf, sfNew, sfProcess;
296375d3a19aSMatthew G. Knepley   IS                 processRanks;
296475d3a19aSMatthew G. Knepley   MPI_Datatype       depthType;
296575d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
296675d3a19aSMatthew G. Knepley   const PetscInt    *localPoints, *neighbors;
296775d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
296875d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
296975d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
297075d3a19aSMatthew G. Knepley   PetscInt          *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
297175d3a19aSMatthew G. Knepley   PetscInt           depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n;
297275d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
297375d3a19aSMatthew G. Knepley 
297475d3a19aSMatthew G. Knepley   PetscFunctionBegin;
297575d3a19aSMatthew G. Knepley   ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr);
297675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
297775d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
297875d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
297975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
298075d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
298175d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
298275d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
298375d3a19aSMatthew G. Knepley   switch (refiner) {
298475d3a19aSMatthew G. Knepley   case 3:
298575d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
298675d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
298775d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
298875d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
298975d3a19aSMatthew G. Knepley   }
299075d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
299175d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr);
299275d3a19aSMatthew G. Knepley   /* Caculate size of new SF */
299375d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
299475d3a19aSMatthew G. Knepley   if (numRoots < 0) PetscFunctionReturn(0);
299575d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
299675d3a19aSMatthew G. Knepley     const PetscInt p = localPoints[l];
299775d3a19aSMatthew G. Knepley 
299875d3a19aSMatthew G. Knepley     switch (refiner) {
299975d3a19aSMatthew G. Knepley     case 1:
300075d3a19aSMatthew G. Knepley       /* Simplicial 2D */
300175d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
300275d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
300375d3a19aSMatthew G. Knepley         ++numLeavesNew;
300475d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
300575d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
3006d963de37SMatthew G. Knepley         numLeavesNew += 2 + 1;
300775d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
300875d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
300975d3a19aSMatthew G. Knepley         numLeavesNew += 4 + 3;
301075d3a19aSMatthew G. Knepley       }
301175d3a19aSMatthew G. Knepley       break;
301275d3a19aSMatthew G. Knepley     case 2:
301375d3a19aSMatthew G. Knepley       /* Hex 2D */
301475d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
301575d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
301675d3a19aSMatthew G. Knepley         ++numLeavesNew;
301775d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
301875d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
3019d963de37SMatthew G. Knepley         numLeavesNew += 2 + 1;
302075d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
3021455d6cd4SMatthew G. Knepley         /* Old cells add new cells, interior faces, and vertex */
3022455d6cd4SMatthew G. Knepley         numLeavesNew += 4 + 4 + 1;
302375d3a19aSMatthew G. Knepley       }
302475d3a19aSMatthew G. Knepley       break;
3025b5da9499SMatthew G. Knepley     case 5:
3026b5da9499SMatthew G. Knepley       /* Simplicial 3D */
3027b5da9499SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
3028b5da9499SMatthew G. Knepley         /* Old vertices stay the same */
3029b5da9499SMatthew G. Knepley         ++numLeavesNew;
3030b5da9499SMatthew G. Knepley       } else if ((p >= eStart) && (p < eEnd)) {
3031b5da9499SMatthew G. Knepley         /* Old edges add new edges and vertex */
3032b5da9499SMatthew G. Knepley         numLeavesNew += 2 + 1;
3033b5da9499SMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
3034b5da9499SMatthew G. Knepley         /* Old faces add new faces and face edges */
3035b5da9499SMatthew G. Knepley         numLeavesNew += 4 + 3;
3036b5da9499SMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
3037b5da9499SMatthew G. Knepley         /* Old cells add new cells and interior faces and edges */
3038b5da9499SMatthew G. Knepley         numLeavesNew += 8 + 8 + 1;
3039b5da9499SMatthew G. Knepley       }
3040b5da9499SMatthew G. Knepley       break;
30412eabf88fSMatthew G. Knepley     case 6:
30422eabf88fSMatthew G. Knepley       /* Hex 3D */
30432eabf88fSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
30442eabf88fSMatthew G. Knepley         /* Old vertices stay the same */
30452eabf88fSMatthew G. Knepley         ++numLeavesNew;
30462eabf88fSMatthew G. Knepley       } else if ((p >= eStart) && (p < eEnd)) {
30472eabf88fSMatthew G. Knepley         /* Old edges add new edges, and vertex */
30482eabf88fSMatthew G. Knepley         numLeavesNew += 2 + 1;
30492eabf88fSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
30502eabf88fSMatthew G. Knepley         /* Old faces add new faces, edges, and vertex */
30512eabf88fSMatthew G. Knepley         numLeavesNew += 4 + 4 + 1;
30522eabf88fSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
30532eabf88fSMatthew G. Knepley         /* Old cells add new cells, faces, edges, and vertex */
30542eabf88fSMatthew G. Knepley         numLeavesNew += 8 + 12 + 6 + 1;
30552eabf88fSMatthew G. Knepley       }
30562eabf88fSMatthew G. Knepley       break;
305775d3a19aSMatthew G. Knepley     default:
305875d3a19aSMatthew G. Knepley       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
305975d3a19aSMatthew G. Knepley     }
306075d3a19aSMatthew G. Knepley   }
306175d3a19aSMatthew G. Knepley   /* Communicate depthSizes for each remote rank */
306275d3a19aSMatthew G. Knepley   ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr);
306375d3a19aSMatthew G. Knepley   ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr);
306475d3a19aSMatthew G. Knepley   ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr);
306575d3a19aSMatthew G. Knepley   ierr = PetscMalloc7(depth+1,PetscInt,&depthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthMaxOld,numNeighbors,PetscInt,&rvStart,numNeighbors,PetscInt,&reStart,numNeighbors,PetscInt,&rfStart,numNeighbors,PetscInt,&rcStart);CHKERRQ(ierr);
306675d3a19aSMatthew G. Knepley   ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr);
306775d3a19aSMatthew G. Knepley   ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr);
306875d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
306975d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
307075d3a19aSMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {
307175d3a19aSMatthew G. Knepley     ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr);
307275d3a19aSMatthew G. Knepley   }
307375d3a19aSMatthew G. Knepley   depthSizeOld[depth]   = cMax;
307475d3a19aSMatthew G. Knepley   depthSizeOld[0]       = vMax;
307575d3a19aSMatthew G. Knepley   depthSizeOld[depth-1] = fMax;
307675d3a19aSMatthew G. Knepley   depthSizeOld[1]       = eMax;
307775d3a19aSMatthew G. Knepley 
307875d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
307975d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
308075d3a19aSMatthew G. Knepley 
308175d3a19aSMatthew G. Knepley   depthSizeOld[depth]   = cEnd - cStart;
308275d3a19aSMatthew G. Knepley   depthSizeOld[0]       = vEnd - vStart;
308375d3a19aSMatthew G. Knepley   depthSizeOld[depth-1] = fEnd - fStart;
308475d3a19aSMatthew G. Knepley   depthSizeOld[1]       = eEnd - eStart;
308575d3a19aSMatthew G. Knepley 
308675d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
308775d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
308875d3a19aSMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {
308975d3a19aSMatthew G. Knepley     ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr);
309075d3a19aSMatthew G. Knepley   }
309175d3a19aSMatthew G. Knepley   ierr = MPI_Type_free(&depthType);CHKERRQ(ierr);
309275d3a19aSMatthew G. Knepley   ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr);
309375d3a19aSMatthew G. Knepley   /* Calculate new point SF */
309475d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt),    &localPointsNew);CHKERRQ(ierr);
309575d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr);
309675d3a19aSMatthew G. Knepley   ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr);
309775d3a19aSMatthew G. Knepley   for (l = 0, m = 0; l < numLeaves; ++l) {
309875d3a19aSMatthew G. Knepley     PetscInt    p     = localPoints[l];
309975d3a19aSMatthew G. Knepley     PetscInt    rp    = remotePoints[l].index, n;
310075d3a19aSMatthew G. Knepley     PetscMPIInt rrank = remotePoints[l].rank;
310175d3a19aSMatthew G. Knepley 
310275d3a19aSMatthew G. Knepley     ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr);
310375d3a19aSMatthew G. Knepley     if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank);
310475d3a19aSMatthew G. Knepley     switch (refiner) {
310575d3a19aSMatthew G. Knepley     case 1:
310675d3a19aSMatthew G. Knepley       /* Simplicial 2D */
310775d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
310875d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
310975d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
311075d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
311175d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
311275d3a19aSMatthew G. Knepley         ++m;
311375d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
311475d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
311575d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
311675d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
311775d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
311875d3a19aSMatthew G. Knepley         ++m;
311975d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
312075d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
312175d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
312275d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
312375d3a19aSMatthew G. Knepley         }
312475d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
312575d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
312675d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
312775d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
312875d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
312975d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
313075d3a19aSMatthew G. Knepley         }
313175d3a19aSMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
313275d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*3     + r;
313375d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r;
313475d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
313575d3a19aSMatthew G. Knepley         }
313675d3a19aSMatthew G. Knepley       }
313775d3a19aSMatthew G. Knepley       break;
313875d3a19aSMatthew G. Knepley     case 2:
313975d3a19aSMatthew G. Knepley       /* Hex 2D */
314075d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
314175d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
314275d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
314375d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
314475d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
314575d3a19aSMatthew G. Knepley         ++m;
314675d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
314775d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
314875d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
314975d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
315075d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
315175d3a19aSMatthew G. Knepley         ++m;
315275d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
315375d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
315475d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
315575d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
315675d3a19aSMatthew G. Knepley         }
315775d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
3158455d6cd4SMatthew G. Knepley         /* Old cells add new cells, interior faces, and vertex */
315975d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
316075d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
316175d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
316275d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
316375d3a19aSMatthew G. Knepley         }
316475d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
316575d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*4     + r;
316675d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r;
316775d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
316875d3a19aSMatthew G. Knepley         }
3169455d6cd4SMatthew G. Knepley         for (r = 0; r < 1; ++r, ++m) {
3170455d6cd4SMatthew G. Knepley           localPointsNew[m]        = vStartNew     + (fEnd - fStart)                    + (p  - cStart)     + r;
3171455d6cd4SMatthew G. Knepley           remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]) + r;
3172455d6cd4SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
3173455d6cd4SMatthew G. Knepley         }
317475d3a19aSMatthew G. Knepley       }
317575d3a19aSMatthew G. Knepley       break;
317675d3a19aSMatthew G. Knepley     case 3:
317775d3a19aSMatthew G. Knepley       /* Hybrid simplicial 2D */
317875d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
317975d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
318075d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
318175d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
318275d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
318375d3a19aSMatthew G. Knepley         ++m;
318475d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fMax)) {
318575d3a19aSMatthew G. Knepley         /* Old interior faces add new faces and vertex */
318675d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
318775d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
318875d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
318975d3a19aSMatthew G. Knepley         ++m;
319075d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
319175d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
319275d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
319375d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
319475d3a19aSMatthew G. Knepley         }
319575d3a19aSMatthew G. Knepley       } else if ((p >= fMax) && (p < fEnd)) {
319675d3a19aSMatthew G. Knepley         /* Old hybrid faces stay the same */
319775d3a19aSMatthew G. Knepley         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - fMax);
319875d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
319975d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
320075d3a19aSMatthew G. Knepley         ++m;
320175d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cMax)) {
320275d3a19aSMatthew G. Knepley         /* Old interior cells add new cells and interior faces */
320375d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
320475d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
320575d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
320675d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
320775d3a19aSMatthew G. Knepley         }
320875d3a19aSMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
320975d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - cStart)*3     + r;
321075d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r;
321175d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
321275d3a19aSMatthew G. Knepley         }
321375d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cMax)) {
321475d3a19aSMatthew G. Knepley         /* Old hybrid cells add new cells and hybrid face */
321575d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
321675d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
321775d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
321875d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
321975d3a19aSMatthew G. Knepley         }
322075d3a19aSMatthew G. Knepley         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (cMax                            - cStart)*3     + (p  - cMax);
322175d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*3 + (rp - rdepthMaxOld[n*(depth+1)+depth]);
322275d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
322375d3a19aSMatthew G. Knepley         ++m;
322475d3a19aSMatthew G. Knepley       }
322575d3a19aSMatthew G. Knepley       break;
3226b5da9499SMatthew G. Knepley     case 5:
3227b5da9499SMatthew G. Knepley       /* Simplicial 3D */
3228b5da9499SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
3229b5da9499SMatthew G. Knepley         /* Old vertices stay the same */
3230b5da9499SMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
3231b5da9499SMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
3232b5da9499SMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
3233b5da9499SMatthew G. Knepley         ++m;
323487fe6628SMatthew G. Knepley       } else if ((p >= eStart) && (p < eEnd)) {
3235b5da9499SMatthew G. Knepley         /* Old edges add new edges and vertex */
3236b5da9499SMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
3237b5da9499SMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
3238b5da9499SMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
3239b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
3240b5da9499SMatthew G. Knepley         }
3241b5da9499SMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
3242b5da9499SMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
3243b5da9499SMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
3244b5da9499SMatthew G. Knepley         ++m;
3245b5da9499SMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
3246b5da9499SMatthew G. Knepley         /* Old faces add new faces and face edges */
3247b5da9499SMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
3248b5da9499SMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
3249b5da9499SMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
3250b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
3251b5da9499SMatthew G. Knepley         }
3252b5da9499SMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
3253b5da9499SMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (p  - fStart)*3     + r;
3254b5da9499SMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + (rp - rfStart[n])*3 + r;
3255b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
3256b5da9499SMatthew G. Knepley         }
3257b5da9499SMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
3258b5da9499SMatthew G. Knepley         /* Old cells add new cells and interior faces and edges */
3259b5da9499SMatthew G. Knepley         for (r = 0; r < 8; ++r, ++m) {
3260b5da9499SMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
3261b5da9499SMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
3262b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
3263b5da9499SMatthew G. Knepley         }
3264b5da9499SMatthew G. Knepley         for (r = 0; r < 8; ++r, ++m) {
3265b5da9499SMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*4                    + (p  - cStart)*8     + r;
3266b5da9499SMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*8 + r;
3267b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
3268b5da9499SMatthew G. Knepley         }
3269b5da9499SMatthew G. Knepley         for (r = 0; r < 1; ++r, ++m) {
3270b5da9499SMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (fEnd - fStart)*3                    + (p  - cStart)*1     + r;
3271b5da9499SMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + rdepthSizeOld[n*(depth+1)+depth-1]*3 + (rp - rcStart[n])*1 + r;
3272b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
3273b5da9499SMatthew G. Knepley         }
3274b5da9499SMatthew G. Knepley       }
3275b5da9499SMatthew G. Knepley       break;
32762eabf88fSMatthew G. Knepley     case 6:
32772eabf88fSMatthew G. Knepley       /* Hex 3D */
32782eabf88fSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
32792eabf88fSMatthew G. Knepley         /* Old vertices stay the same */
32802eabf88fSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
32812eabf88fSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
32822eabf88fSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
32832eabf88fSMatthew G. Knepley         ++m;
32842eabf88fSMatthew G. Knepley       } else if ((p >= eStart) && (p < eEnd)) {
32852eabf88fSMatthew G. Knepley         /* Old edges add new edges and vertex */
32862eabf88fSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
32872eabf88fSMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
32882eabf88fSMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
32892eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
32902eabf88fSMatthew G. Knepley         }
32912eabf88fSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
32922eabf88fSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
32932eabf88fSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
32942eabf88fSMatthew G. Knepley         ++m;
32952eabf88fSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
32962eabf88fSMatthew G. Knepley         /* Old faces add new faces, edges, and vertex */
32972eabf88fSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
32982eabf88fSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
32992eabf88fSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
33002eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
33012eabf88fSMatthew G. Knepley         }
33022eabf88fSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
33032eabf88fSMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (p  - fStart)*4     + r;
33042eabf88fSMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + (rp - rfStart[n])*4 + r;
33052eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
33062eabf88fSMatthew G. Knepley         }
33072eabf88fSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (eEnd - eStart)              + (p  - fStart);
33082eabf88fSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+1] + (rp - rfStart[n]);
33092eabf88fSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
33102eabf88fSMatthew G. Knepley         ++m;
33112eabf88fSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
33122eabf88fSMatthew G. Knepley         /* Old cells add new cells, faces, edges, and vertex */
33132eabf88fSMatthew G. Knepley         for (r = 0; r < 8; ++r, ++m) {
33142eabf88fSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
33152eabf88fSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
33162eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
33172eabf88fSMatthew G. Knepley         }
33182eabf88fSMatthew G. Knepley         for (r = 0; r < 12; ++r, ++m) {
33192eabf88fSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*4                    + (p  - cStart)*12     + r;
33202eabf88fSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*12 + r;
33212eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
33222eabf88fSMatthew G. Knepley         }
33232eabf88fSMatthew G. Knepley         for (r = 0; r < 6; ++r, ++m) {
33242eabf88fSMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (fEnd - fStart)*4                    + (p  - cStart)*6     + r;
33252eabf88fSMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*6 + r;
33262eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
33272eabf88fSMatthew G. Knepley         }
33282eabf88fSMatthew G. Knepley         for (r = 0; r < 1; ++r, ++m) {
33292eabf88fSMatthew G. Knepley           localPointsNew[m]        = vStartNew     + (eEnd - eStart)              + (fEnd - fStart)                    + (p  - cStart)     + r;
33302eabf88fSMatthew G. Knepley           remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+1] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]) + r;
33312eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
33322eabf88fSMatthew G. Knepley         }
33332eabf88fSMatthew G. Knepley       }
33342eabf88fSMatthew G. Knepley       break;
333575d3a19aSMatthew G. Knepley     default:
333675d3a19aSMatthew G. Knepley       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
333775d3a19aSMatthew G. Knepley     }
333875d3a19aSMatthew G. Knepley   }
333975d3a19aSMatthew G. Knepley   ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr);
334075d3a19aSMatthew G. Knepley   ierr = ISDestroy(&processRanks);CHKERRQ(ierr);
334175d3a19aSMatthew G. Knepley   ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
334275d3a19aSMatthew G. Knepley   ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr);
334306a0ba2dSMatthew G. Knepley   ierr = PetscFree7(depthSizeOld,rdepthSizeOld,rdepthMaxOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr);
334475d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
334575d3a19aSMatthew G. Knepley }
334675d3a19aSMatthew G. Knepley 
334775d3a19aSMatthew G. Knepley #undef __FUNCT__
334875d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerCreateLabels"
334975d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
335075d3a19aSMatthew G. Knepley {
335175d3a19aSMatthew G. Knepley   PetscInt       numLabels, l;
3352b5da9499SMatthew G. Knepley   PetscInt       depth, newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r;
335375d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
335475d3a19aSMatthew G. Knepley 
335575d3a19aSMatthew G. Knepley   PetscFunctionBegin;
335675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
335775d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
335875d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
335975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
3360d963de37SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
3361d963de37SMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
336275d3a19aSMatthew G. Knepley   ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
336375d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
336475d3a19aSMatthew G. Knepley   switch (refiner) {
336575d3a19aSMatthew G. Knepley   case 3:
336675d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
336775d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
336875d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
336975d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
337075d3a19aSMatthew G. Knepley   }
337175d3a19aSMatthew G. Knepley   for (l = 0; l < numLabels; ++l) {
337275d3a19aSMatthew G. Knepley     DMLabel         label, labelNew;
337375d3a19aSMatthew G. Knepley     const char     *lname;
337475d3a19aSMatthew G. Knepley     PetscBool       isDepth;
337575d3a19aSMatthew G. Knepley     IS              valueIS;
337675d3a19aSMatthew G. Knepley     const PetscInt *values;
337775d3a19aSMatthew G. Knepley     PetscInt        numValues, val;
337875d3a19aSMatthew G. Knepley 
337975d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr);
338075d3a19aSMatthew G. Knepley     ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr);
338175d3a19aSMatthew G. Knepley     if (isDepth) continue;
338275d3a19aSMatthew G. Knepley     ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr);
338375d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr);
338475d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr);
338575d3a19aSMatthew G. Knepley     ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
338675d3a19aSMatthew G. Knepley     ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr);
338775d3a19aSMatthew G. Knepley     ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
338875d3a19aSMatthew G. Knepley     for (val = 0; val < numValues; ++val) {
338975d3a19aSMatthew G. Knepley       IS              pointIS;
339075d3a19aSMatthew G. Knepley       const PetscInt *points;
339175d3a19aSMatthew G. Knepley       PetscInt        numPoints, n;
339275d3a19aSMatthew G. Knepley 
339375d3a19aSMatthew G. Knepley       ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr);
339475d3a19aSMatthew G. Knepley       ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
339575d3a19aSMatthew G. Knepley       ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
339675d3a19aSMatthew G. Knepley       for (n = 0; n < numPoints; ++n) {
339775d3a19aSMatthew G. Knepley         const PetscInt p = points[n];
339875d3a19aSMatthew G. Knepley         switch (refiner) {
339975d3a19aSMatthew G. Knepley         case 1:
340075d3a19aSMatthew G. Knepley           /* Simplicial 2D */
340175d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
340275d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
340375d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
340475d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
340575d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
340675d3a19aSMatthew G. Knepley             /* Old faces add new faces and vertex */
340775d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
340875d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
340975d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
341075d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
341175d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
341275d3a19aSMatthew G. Knepley             }
341375d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
341475d3a19aSMatthew G. Knepley             /* Old cells add new cells and interior faces */
341575d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
341675d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
341775d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
341875d3a19aSMatthew G. Knepley             }
341975d3a19aSMatthew G. Knepley             for (r = 0; r < 3; ++r) {
342075d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
342175d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
342275d3a19aSMatthew G. Knepley             }
342375d3a19aSMatthew G. Knepley           }
342475d3a19aSMatthew G. Knepley           break;
342575d3a19aSMatthew G. Knepley         case 2:
342675d3a19aSMatthew G. Knepley           /* Hex 2D */
342775d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
342875d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
342975d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
343075d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
343175d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
343275d3a19aSMatthew G. Knepley             /* Old faces add new faces and vertex */
343375d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
343475d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
343575d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
343675d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
343775d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
343875d3a19aSMatthew G. Knepley             }
343975d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
344075d3a19aSMatthew G. Knepley             /* Old cells add new cells and interior faces and vertex */
344175d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
344275d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
344375d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
344475d3a19aSMatthew G. Knepley             }
344575d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
344675d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
344775d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
344875d3a19aSMatthew G. Knepley             }
344975d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
345075d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
345175d3a19aSMatthew G. Knepley           }
345275d3a19aSMatthew G. Knepley           break;
345375d3a19aSMatthew G. Knepley         case 3:
345475d3a19aSMatthew G. Knepley           /* Hybrid simplicial 2D */
345575d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
345675d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
345775d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
345875d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
345975d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fMax)) {
346075d3a19aSMatthew G. Knepley             /* Old interior faces add new faces and vertex */
346175d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
346275d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
346375d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
346475d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
346575d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
346675d3a19aSMatthew G. Knepley             }
346775d3a19aSMatthew G. Knepley           } else if ((p >= fMax) && (p < fEnd)) {
346875d3a19aSMatthew G. Knepley             /* Old hybrid faces stay the same */
346975d3a19aSMatthew G. Knepley             newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
347075d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
347175d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cMax)) {
347275d3a19aSMatthew G. Knepley             /* Old interior cells add new cells and interior faces */
347375d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
347475d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
347575d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
347675d3a19aSMatthew G. Knepley             }
347775d3a19aSMatthew G. Knepley             for (r = 0; r < 3; ++r) {
347875d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
347975d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
348075d3a19aSMatthew G. Knepley             }
348175d3a19aSMatthew G. Knepley           } else if ((p >= cMax) && (p < cEnd)) {
348275d3a19aSMatthew G. Knepley             /* Old hybrid cells add new cells and hybrid face */
348375d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
348475d3a19aSMatthew G. Knepley               newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
348575d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
348675d3a19aSMatthew G. Knepley             }
348775d3a19aSMatthew G. Knepley             newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
348875d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
348975d3a19aSMatthew G. Knepley           }
349075d3a19aSMatthew G. Knepley           break;
3491b5da9499SMatthew G. Knepley         case 5:
3492b5da9499SMatthew G. Knepley           /* Simplicial 3D */
3493b5da9499SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
3494b5da9499SMatthew G. Knepley             /* Old vertices stay the same */
3495b5da9499SMatthew G. Knepley             newp = vStartNew + (p - vStart);
3496b5da9499SMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3497b5da9499SMatthew G. Knepley           } else if ((p >= eStart) && (p < eEnd)) {
3498b5da9499SMatthew G. Knepley             /* Old edges add new edges and vertex */
3499b5da9499SMatthew G. Knepley             for (r = 0; r < 2; ++r) {
3500b5da9499SMatthew G. Knepley               newp = eStartNew + (p - eStart)*2 + r;
3501b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3502b5da9499SMatthew G. Knepley             }
3503b5da9499SMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - eStart);
3504b5da9499SMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3505b5da9499SMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
3506b5da9499SMatthew G. Knepley             /* Old faces add new faces and edges */
3507b5da9499SMatthew G. Knepley             for (r = 0; r < 4; ++r) {
3508b5da9499SMatthew G. Knepley               newp = fStartNew + (p - fStart)*4 + r;
3509b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3510b5da9499SMatthew G. Knepley             }
3511b5da9499SMatthew G. Knepley             for (r = 0; r < 3; ++r) {
3512b5da9499SMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
3513b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3514b5da9499SMatthew G. Knepley             }
3515b5da9499SMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
3516b5da9499SMatthew G. Knepley             /* Old cells add new cells and interior faces and edges */
3517b5da9499SMatthew G. Knepley             for (r = 0; r < 8; ++r) {
3518b5da9499SMatthew G. Knepley               newp = cStartNew + (p - cStart)*8 + r;
3519b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3520b5da9499SMatthew G. Knepley             }
3521b5da9499SMatthew G. Knepley             for (r = 0; r < 8; ++r) {
3522b5da9499SMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*8 + r;
3523b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3524b5da9499SMatthew G. Knepley             }
3525b5da9499SMatthew G. Knepley             for (r = 0; r < 1; ++r) {
3526b5da9499SMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*1 + r;
3527b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3528b5da9499SMatthew G. Knepley             }
3529b5da9499SMatthew G. Knepley           }
3530b5da9499SMatthew G. Knepley           break;
35312eabf88fSMatthew G. Knepley         case 6:
35322eabf88fSMatthew G. Knepley           /* Hex 3D */
35332eabf88fSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
35342eabf88fSMatthew G. Knepley             /* Old vertices stay the same */
35352eabf88fSMatthew G. Knepley             newp = vStartNew + (p - vStart);
35362eabf88fSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
35372eabf88fSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
35382eabf88fSMatthew G. Knepley             /* Old edges add new edges and vertex */
35392eabf88fSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
35402eabf88fSMatthew G. Knepley               newp = eStartNew + (p - eStart)*2 + r;
35412eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
35422eabf88fSMatthew G. Knepley             }
35432eabf88fSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - eStart);
35442eabf88fSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
35452eabf88fSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
35462eabf88fSMatthew G. Knepley             /* Old faces add new faces, edges, and vertex */
35472eabf88fSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
35482eabf88fSMatthew G. Knepley               newp = fStartNew + (p - fStart)*4 + r;
35492eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
35502eabf88fSMatthew G. Knepley             }
35512eabf88fSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
35522eabf88fSMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*4 + r;
35532eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
35542eabf88fSMatthew G. Knepley             }
35552eabf88fSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (p - fStart);
35562eabf88fSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
35572eabf88fSMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
35582eabf88fSMatthew G. Knepley             /* Old cells add new cells, faces, edges, and vertex */
35592eabf88fSMatthew G. Knepley             for (r = 0; r < 8; ++r) {
35602eabf88fSMatthew G. Knepley               newp = cStartNew + (p - cStart)*8 + r;
35612eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
35622eabf88fSMatthew G. Knepley             }
35632eabf88fSMatthew G. Knepley             for (r = 0; r < 12; ++r) {
35642eabf88fSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*12 + r;
35652eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
35662eabf88fSMatthew G. Knepley             }
35672eabf88fSMatthew G. Knepley             for (r = 0; r < 6; ++r) {
35682eabf88fSMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (p - cStart)*6 + r;
35692eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
35702eabf88fSMatthew G. Knepley             }
35712eabf88fSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (p - cStart);
35722eabf88fSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
35732eabf88fSMatthew G. Knepley           }
35742eabf88fSMatthew G. Knepley           break;
357575d3a19aSMatthew G. Knepley         default:
357675d3a19aSMatthew G. Knepley           SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
357775d3a19aSMatthew G. Knepley         }
357875d3a19aSMatthew G. Knepley       }
357975d3a19aSMatthew G. Knepley       ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
358075d3a19aSMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
358175d3a19aSMatthew G. Knepley     }
358275d3a19aSMatthew G. Knepley     ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
358375d3a19aSMatthew G. Knepley     ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
358475d3a19aSMatthew G. Knepley     if (0) {
358575d3a19aSMatthew G. Knepley       ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr);
358675d3a19aSMatthew G. Knepley       ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
358775d3a19aSMatthew G. Knepley       ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
358875d3a19aSMatthew G. Knepley     }
358975d3a19aSMatthew G. Knepley   }
359075d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
359175d3a19aSMatthew G. Knepley }
359275d3a19aSMatthew G. Knepley 
359375d3a19aSMatthew G. Knepley #undef __FUNCT__
3594509c9b89SMatthew G. Knepley #define __FUNCT__ "DMPlexRefineUniform_Internal"
359575d3a19aSMatthew G. Knepley /* This will only work for interpolated meshes */
3596509c9b89SMatthew G. Knepley PetscErrorCode DMPlexRefineUniform_Internal(DM dm, CellRefiner cellRefiner, DM *dmRefined)
359775d3a19aSMatthew G. Knepley {
359875d3a19aSMatthew G. Knepley   DM             rdm;
359975d3a19aSMatthew G. Knepley   PetscInt      *depthSize;
360075d3a19aSMatthew G. Knepley   PetscInt       dim, depth = 0, d, pStart = 0, pEnd = 0;
360175d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
360275d3a19aSMatthew G. Knepley 
360375d3a19aSMatthew G. Knepley   PetscFunctionBegin;
360475d3a19aSMatthew G. Knepley   ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr);
360575d3a19aSMatthew G. Knepley   ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr);
360675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
360775d3a19aSMatthew G. Knepley   ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr);
360875d3a19aSMatthew G. Knepley   /* Calculate number of new points of each depth */
360975d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
361075d3a19aSMatthew G. Knepley   ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr);
361175d3a19aSMatthew G. Knepley   ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr);
361275d3a19aSMatthew G. Knepley   ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr);
361375d3a19aSMatthew G. Knepley   /* Step 1: Set chart */
361475d3a19aSMatthew G. Knepley   for (d = 0; d <= depth; ++d) pEnd += depthSize[d];
361575d3a19aSMatthew G. Knepley   ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr);
361675d3a19aSMatthew G. Knepley   /* Step 2: Set cone/support sizes */
361775d3a19aSMatthew G. Knepley   ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
361875d3a19aSMatthew G. Knepley   /* Step 3: Setup refined DM */
361975d3a19aSMatthew G. Knepley   ierr = DMSetUp(rdm);CHKERRQ(ierr);
362075d3a19aSMatthew G. Knepley   /* Step 4: Set cones and supports */
362175d3a19aSMatthew G. Knepley   ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
362275d3a19aSMatthew G. Knepley   /* Step 5: Stratify */
362375d3a19aSMatthew G. Knepley   ierr = DMPlexStratify(rdm);CHKERRQ(ierr);
362475d3a19aSMatthew G. Knepley   /* Step 6: Set coordinates for vertices */
362575d3a19aSMatthew G. Knepley   ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
362675d3a19aSMatthew G. Knepley   /* Step 7: Create pointSF */
362775d3a19aSMatthew G. Knepley   ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
362875d3a19aSMatthew G. Knepley   /* Step 8: Create labels */
362975d3a19aSMatthew G. Knepley   ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
363075d3a19aSMatthew G. Knepley   ierr = PetscFree(depthSize);CHKERRQ(ierr);
363175d3a19aSMatthew G. Knepley 
363275d3a19aSMatthew G. Knepley   *dmRefined = rdm;
363375d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
363475d3a19aSMatthew G. Knepley }
363575d3a19aSMatthew G. Knepley 
363675d3a19aSMatthew G. Knepley #undef __FUNCT__
363775d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexSetRefinementUniform"
363875d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
363975d3a19aSMatthew G. Knepley {
364075d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
364175d3a19aSMatthew G. Knepley 
364275d3a19aSMatthew G. Knepley   PetscFunctionBegin;
364375d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
364475d3a19aSMatthew G. Knepley   mesh->refinementUniform = refinementUniform;
364575d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
364675d3a19aSMatthew G. Knepley }
364775d3a19aSMatthew G. Knepley 
364875d3a19aSMatthew G. Knepley #undef __FUNCT__
364975d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexGetRefinementUniform"
365075d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
365175d3a19aSMatthew G. Knepley {
365275d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
365375d3a19aSMatthew G. Knepley 
365475d3a19aSMatthew G. Knepley   PetscFunctionBegin;
365575d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
365675d3a19aSMatthew G. Knepley   PetscValidPointer(refinementUniform,  2);
365775d3a19aSMatthew G. Knepley   *refinementUniform = mesh->refinementUniform;
365875d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
365975d3a19aSMatthew G. Knepley }
366075d3a19aSMatthew G. Knepley 
366175d3a19aSMatthew G. Knepley #undef __FUNCT__
366275d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexSetRefinementLimit"
366375d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
366475d3a19aSMatthew G. Knepley {
366575d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
366675d3a19aSMatthew G. Knepley 
366775d3a19aSMatthew G. Knepley   PetscFunctionBegin;
366875d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
366975d3a19aSMatthew G. Knepley   mesh->refinementLimit = refinementLimit;
367075d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
367175d3a19aSMatthew G. Knepley }
367275d3a19aSMatthew G. Knepley 
367375d3a19aSMatthew G. Knepley #undef __FUNCT__
367475d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexGetRefinementLimit"
367575d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
367675d3a19aSMatthew G. Knepley {
367775d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
367875d3a19aSMatthew G. Knepley 
367975d3a19aSMatthew G. Knepley   PetscFunctionBegin;
368075d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
368175d3a19aSMatthew G. Knepley   PetscValidPointer(refinementLimit,  2);
368275d3a19aSMatthew G. Knepley   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
368375d3a19aSMatthew G. Knepley   *refinementLimit = mesh->refinementLimit;
368475d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
368575d3a19aSMatthew G. Knepley }
368675d3a19aSMatthew G. Knepley 
368775d3a19aSMatthew G. Knepley #undef __FUNCT__
3688509c9b89SMatthew G. Knepley #define __FUNCT__ "DMPlexGetCellRefiner_Internal"
3689509c9b89SMatthew G. Knepley PetscErrorCode DMPlexGetCellRefiner_Internal(DM dm, CellRefiner *cellRefiner)
369075d3a19aSMatthew G. Knepley {
369175d3a19aSMatthew G. Knepley   PetscInt       dim, cStart, coneSize, cMax;
369275d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
369375d3a19aSMatthew G. Knepley 
369475d3a19aSMatthew G. Knepley   PetscFunctionBegin;
369575d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
369675d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr);
369775d3a19aSMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr);
369875d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr);
369975d3a19aSMatthew G. Knepley   switch (dim) {
370075d3a19aSMatthew G. Knepley   case 2:
370175d3a19aSMatthew G. Knepley     switch (coneSize) {
370275d3a19aSMatthew G. Knepley     case 3:
370375d3a19aSMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 3; /* Hybrid */
370475d3a19aSMatthew G. Knepley       else *cellRefiner = 1; /* Triangular */
370575d3a19aSMatthew G. Knepley       break;
370675d3a19aSMatthew G. Knepley     case 4:
370775d3a19aSMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 4; /* Hybrid */
370875d3a19aSMatthew G. Knepley       else *cellRefiner = 2; /* Quadrilateral */
370975d3a19aSMatthew G. Knepley       break;
371075d3a19aSMatthew G. Knepley     default:
371175d3a19aSMatthew G. Knepley       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
371275d3a19aSMatthew G. Knepley     }
371375d3a19aSMatthew G. Knepley     break;
3714b5da9499SMatthew G. Knepley   case 3:
3715b5da9499SMatthew G. Knepley     switch (coneSize) {
3716b5da9499SMatthew G. Knepley     case 4:
3717b5da9499SMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 7; /* Hybrid */
3718b5da9499SMatthew G. Knepley       else *cellRefiner = 5; /* Tetrahedral */
3719b5da9499SMatthew G. Knepley       break;
37202eabf88fSMatthew G. Knepley     case 6:
37212eabf88fSMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 8; /* Hybrid */
37222eabf88fSMatthew G. Knepley       else *cellRefiner = 6; /* hexahedral */
37232eabf88fSMatthew G. Knepley       break;
3724b5da9499SMatthew G. Knepley     default:
3725b5da9499SMatthew G. Knepley       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
3726b5da9499SMatthew G. Knepley     }
3727b5da9499SMatthew G. Knepley     break;
372875d3a19aSMatthew G. Knepley   default:
372975d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim);
373075d3a19aSMatthew G. Knepley   }
373175d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
373275d3a19aSMatthew G. Knepley }
3733