xref: /petsc/src/dm/impls/plex/plexrefine.c (revision aaebbb9d5a0778a456d1d42f6df4be808ccd22b3)
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);
116b5da9499SMatthew G. Knepley     depthSize[0] =    vEnd - vStart  +     eMax - eStart;  /* Add a vertex on every edge, but not hybrid edges */
117b5da9499SMatthew G. Knepley     depthSize[1] = 2*(eMax - eStart) + 13*(cMax - cStart) + (eEnd - eMax) + numHybridFaces; /* Every interior edge is split into 2 edges and 13 edges are added for each interior cell, each hybrid edge stays intact, and one new hybrid edge for each two interior edges (hybrid face) on a hybrid cell */
118b5da9499SMatthew G. Knepley     depthSize[2] = 4*(fEnd - fStart) +  8*(cEnd - cStart); /* Every face split into 4 faces and 8 faces are added for each cell */
119b5da9499SMatthew G. Knepley     depthSize[3] = 8*(cMax - cStart) +  4*(cEnd - cMax);   /* Every interior cell split into 8 cells, and every hybrid cell split into 4 cells */
120b5da9499SMatthew G. Knepley     break;
12175d3a19aSMatthew G. Knepley   default:
12275d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
12375d3a19aSMatthew G. Knepley   }
12475d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
12575d3a19aSMatthew G. Knepley }
12675d3a19aSMatthew G. Knepley 
12742525629SMatthew G. Knepley /* Return triangle edge for orientation o, if it is r for o == 0 */
12842525629SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetTriEdge_Static(PetscInt o, PetscInt r) {
129518a8359SMatthew G. Knepley   return (o < 0 ? 2-(o+r) : o+r)%3;
130518a8359SMatthew G. Knepley }
131518a8359SMatthew G. Knepley 
132518a8359SMatthew G. Knepley /* Return triangle subface for orientation o, if it is r for o == 0 */
133518a8359SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetTriSubface_Static(PetscInt o, PetscInt r) {
134518a8359SMatthew G. Knepley   return (o < 0 ? 0-(o+r) : o+r)%3;
13542525629SMatthew G. Knepley }
13642525629SMatthew G. Knepley 
137e3f8b1d6SMatthew G. Knepley /* Return quad edge for orientation o, if it is r for o == 0 */
138e3f8b1d6SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetQuadEdge_Static(PetscInt o, PetscInt r) {
139e3f8b1d6SMatthew G. Knepley   return (o < 0 ? 3-(o+r) : o+r)%4;
140e3f8b1d6SMatthew G. Knepley }
141e3f8b1d6SMatthew G. Knepley 
142e3f8b1d6SMatthew G. Knepley /* Return quad subface for orientation o, if it is r for o == 0 */
143e3f8b1d6SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetQuadSubface_Static(PetscInt o, PetscInt r) {
144e3f8b1d6SMatthew G. Knepley   return (o < 0 ? 0-(o+r) : o+r)%4;
14542525629SMatthew G. Knepley }
14642525629SMatthew G. Knepley 
14775d3a19aSMatthew G. Knepley #undef __FUNCT__
14875d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetConeSizes"
14975d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
15075d3a19aSMatthew G. Knepley {
151b5da9499SMatthew 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;
15275d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
15375d3a19aSMatthew G. Knepley 
15475d3a19aSMatthew G. Knepley   PetscFunctionBegin;
15575d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
15675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
15775d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
15875d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
15975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
16075d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
16175d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
16275d3a19aSMatthew G. Knepley   switch (refiner) {
16375d3a19aSMatthew G. Knepley   case 1:
16475d3a19aSMatthew G. Knepley     /* Simplicial 2D */
16575d3a19aSMatthew G. Knepley     /* All cells have 3 faces */
16675d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
16775d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
16875d3a19aSMatthew G. Knepley         const PetscInt newp = (c - cStart)*4 + r;
16975d3a19aSMatthew G. Knepley 
17075d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
17175d3a19aSMatthew G. Knepley       }
17275d3a19aSMatthew G. Knepley     }
17375d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
17475d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
17575d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
17675d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
17775d3a19aSMatthew G. Knepley         PetscInt       size;
17875d3a19aSMatthew G. Knepley 
17975d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
18075d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
18175d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
18275d3a19aSMatthew G. Knepley       }
18375d3a19aSMatthew G. Knepley     }
18475d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
18575d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
18675d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
18775d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
18875d3a19aSMatthew G. Knepley 
18975d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
19075d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
19175d3a19aSMatthew G. Knepley       }
19275d3a19aSMatthew G. Knepley     }
19375d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
19475d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
19575d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
19675d3a19aSMatthew G. Knepley       PetscInt       size;
19775d3a19aSMatthew G. Knepley 
19875d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
19975d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
20075d3a19aSMatthew G. Knepley     }
20175d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells*2 supports */
20275d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
20375d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
20475d3a19aSMatthew G. Knepley       PetscInt       size;
20575d3a19aSMatthew G. Knepley 
20675d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
20775d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr);
20875d3a19aSMatthew G. Knepley     }
20975d3a19aSMatthew G. Knepley     break;
21075d3a19aSMatthew G. Knepley   case 2:
21175d3a19aSMatthew G. Knepley     /* Hex 2D */
21275d3a19aSMatthew G. Knepley     /* All cells have 4 faces */
21375d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
21475d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
21575d3a19aSMatthew G. Knepley         const PetscInt newp = (c - cStart)*4 + r;
21675d3a19aSMatthew G. Knepley 
21775d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
21875d3a19aSMatthew G. Knepley       }
21975d3a19aSMatthew G. Knepley     }
22075d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
22175d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
22275d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
22375d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
22475d3a19aSMatthew G. Knepley         PetscInt       size;
22575d3a19aSMatthew G. Knepley 
22675d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
22775d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
22875d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
22975d3a19aSMatthew G. Knepley       }
23075d3a19aSMatthew G. Knepley     }
23175d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
23275d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
23375d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
23475d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
23575d3a19aSMatthew G. Knepley 
23675d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
23775d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
23875d3a19aSMatthew G. Knepley       }
23975d3a19aSMatthew G. Knepley     }
24075d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
24175d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
24275d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
24375d3a19aSMatthew G. Knepley       PetscInt       size;
24475d3a19aSMatthew G. Knepley 
24575d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
24675d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
24775d3a19aSMatthew G. Knepley     }
24875d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells supports */
24975d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
25075d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
25175d3a19aSMatthew G. Knepley       PetscInt       size;
25275d3a19aSMatthew G. Knepley 
25375d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
25475d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
25575d3a19aSMatthew G. Knepley     }
25675d3a19aSMatthew G. Knepley     /* Cell vertices have 4 supports */
25775d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
25875d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
25975d3a19aSMatthew G. Knepley 
26075d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
26175d3a19aSMatthew G. Knepley     }
26275d3a19aSMatthew G. Knepley     break;
26375d3a19aSMatthew G. Knepley   case 3:
264d963de37SMatthew G. Knepley     /* Hybrid Simplicial 2D */
26575d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
26675d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
26775d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
26875d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
26975d3a19aSMatthew G. Knepley     ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
27075d3a19aSMatthew G. Knepley     /* Interior cells have 3 faces */
27175d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
27275d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
27375d3a19aSMatthew G. Knepley         const PetscInt newp = cStartNew + (c - cStart)*4 + r;
27475d3a19aSMatthew G. Knepley 
27575d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
27675d3a19aSMatthew G. Knepley       }
27775d3a19aSMatthew G. Knepley     }
27875d3a19aSMatthew G. Knepley     /* Hybrid cells have 4 faces */
27975d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
28075d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
28175d3a19aSMatthew G. Knepley         const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
28275d3a19aSMatthew G. Knepley 
28375d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
28475d3a19aSMatthew G. Knepley       }
28575d3a19aSMatthew G. Knepley     }
28675d3a19aSMatthew G. Knepley     /* Interior split faces have 2 vertices and the same cells as the parent */
28775d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
28875d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
28975d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
29075d3a19aSMatthew G. Knepley         PetscInt       size;
29175d3a19aSMatthew G. Knepley 
29275d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
29375d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
29475d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
29575d3a19aSMatthew G. Knepley       }
29675d3a19aSMatthew G. Knepley     }
29775d3a19aSMatthew G. Knepley     /* Interior cell faces have 2 vertices and 2 cells */
29875d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
29975d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
30075d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
30175d3a19aSMatthew G. Knepley 
30275d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
30375d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
30475d3a19aSMatthew G. Knepley       }
30575d3a19aSMatthew G. Knepley     }
30675d3a19aSMatthew G. Knepley     /* Hybrid faces have 2 vertices and the same cells */
30775d3a19aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
30875d3a19aSMatthew G. Knepley       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
30975d3a19aSMatthew G. Knepley       PetscInt       size;
31075d3a19aSMatthew G. Knepley 
31175d3a19aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
31275d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
31375d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
31475d3a19aSMatthew G. Knepley     }
31575d3a19aSMatthew G. Knepley     /* Hybrid cell faces have 2 vertices and 2 cells */
31675d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
31775d3a19aSMatthew G. Knepley       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
31875d3a19aSMatthew G. Knepley 
31975d3a19aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
32075d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
32175d3a19aSMatthew G. Knepley     }
32275d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
32375d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
32475d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
32575d3a19aSMatthew G. Knepley       PetscInt       size;
32675d3a19aSMatthew G. Knepley 
32775d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
32875d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
32975d3a19aSMatthew G. Knepley     }
33075d3a19aSMatthew G. Knepley     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
33175d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
33275d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
33375d3a19aSMatthew G. Knepley       const PetscInt *support;
33475d3a19aSMatthew G. Knepley       PetscInt       size, newSize = 2, s;
33575d3a19aSMatthew G. Knepley 
33675d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
33775d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
33875d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
33975d3a19aSMatthew G. Knepley         if (support[s] >= cMax) newSize += 1;
34075d3a19aSMatthew G. Knepley         else newSize += 2;
34175d3a19aSMatthew G. Knepley       }
34275d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr);
34375d3a19aSMatthew G. Knepley     }
34475d3a19aSMatthew G. Knepley     break;
345b5da9499SMatthew G. Knepley   case 5:
346b5da9499SMatthew G. Knepley     /* Simplicial 3D */
347b5da9499SMatthew G. Knepley     /* All cells have 4 faces */
348b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
349b5da9499SMatthew G. Knepley       for (r = 0; r < 8; ++r) {
350b5da9499SMatthew G. Knepley         const PetscInt newp = (c - cStart)*8 + r;
351b5da9499SMatthew G. Knepley 
352b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
353b5da9499SMatthew G. Knepley       }
354b5da9499SMatthew G. Knepley     }
355b5da9499SMatthew G. Knepley     /* Split faces have 3 edges and the same cells as the parent */
356b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
357b5da9499SMatthew G. Knepley       for (r = 0; r < 4; ++r) {
358b5da9499SMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
359b5da9499SMatthew G. Knepley         PetscInt       size;
360b5da9499SMatthew G. Knepley 
361b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
362b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
363b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
364b5da9499SMatthew G. Knepley       }
365b5da9499SMatthew G. Knepley     }
366b5da9499SMatthew G. Knepley     /* Interior faces have 3 edges and 2 cells */
367b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
368b5da9499SMatthew G. Knepley       for (r = 0; r < 8; ++r) {
369b5da9499SMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + r;
370b5da9499SMatthew G. Knepley 
371b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
372b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
373b5da9499SMatthew G. Knepley       }
374b5da9499SMatthew G. Knepley     }
375b5da9499SMatthew G. Knepley     /* Split edges have 2 vertices and the same faces */
376b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
377b5da9499SMatthew G. Knepley       for (r = 0; r < 2; ++r) {
378b5da9499SMatthew G. Knepley         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
379b5da9499SMatthew G. Knepley         PetscInt       size;
380b5da9499SMatthew G. Knepley 
381b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
382b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
383b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
384b5da9499SMatthew G. Knepley       }
385b5da9499SMatthew G. Knepley     }
386b5da9499SMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
387b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
388b5da9499SMatthew G. Knepley       for (r = 0; r < 3; ++r) {
389b5da9499SMatthew G. Knepley         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
390b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
391b5da9499SMatthew G. Knepley         PetscInt        coneSize, c, supportSize, s, er, intFaces = 0;
392b5da9499SMatthew G. Knepley 
393b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
394b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
395b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
396b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
397b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
398b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
399b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
400b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
40186f0afeeSMatthew G. Knepley           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
40286f0afeeSMatthew G. Knepley           er = ornt[c] < 0 ? (-(ornt[c]+1) + 2-r)%3 : (ornt[c] + r)%3;
403b5da9499SMatthew G. Knepley           if (er == eint[c]) {
404b5da9499SMatthew G. Knepley             intFaces += 1;
405b5da9499SMatthew G. Knepley           } else {
406b5da9499SMatthew G. Knepley             intFaces += 2;
407b5da9499SMatthew G. Knepley           }
408b5da9499SMatthew G. Knepley         }
409b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2+intFaces);CHKERRQ(ierr);
410b5da9499SMatthew G. Knepley       }
411b5da9499SMatthew G. Knepley     }
412b5da9499SMatthew G. Knepley     /* Interior edges have 2 vertices and 4 faces */
413b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
414b5da9499SMatthew G. Knepley       const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
415b5da9499SMatthew G. Knepley 
416b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
417b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
418b5da9499SMatthew G. Knepley     }
419b5da9499SMatthew G. Knepley     /* Old vertices have identical supports */
420b5da9499SMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
421b5da9499SMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
422b5da9499SMatthew G. Knepley       PetscInt       size;
423b5da9499SMatthew G. Knepley 
424b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
425b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
426b5da9499SMatthew G. Knepley     }
427b5da9499SMatthew G. Knepley     /* Edge vertices have 2 + faces*2 + cells*0/1 supports */
428b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
429b5da9499SMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
430b5da9499SMatthew G. Knepley       PetscInt       size, *star = NULL, starSize, s, cellSize = 0;
431b5da9499SMatthew G. Knepley 
432b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
433b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
434b5da9499SMatthew G. Knepley       for (s = 0; s < starSize*2; s += 2) {
435b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt;
436b5da9499SMatthew G. Knepley         PetscInt        e01, e23;
437b5da9499SMatthew G. Knepley 
438b5da9499SMatthew G. Knepley         if ((star[s] >= cStart) && (star[s] < cEnd)) {
439b5da9499SMatthew G. Knepley           /* Check edge 0-1 */
440b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
441b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
442b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
44342525629SMatthew G. Knepley           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
444b5da9499SMatthew G. Knepley           /* Check edge 2-3 */
445b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
446b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
44742525629SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
44842525629SMatthew G. Knepley           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
449b5da9499SMatthew G. Knepley           if ((e01 == e) || (e23 == e)) ++cellSize;
450b5da9499SMatthew G. Knepley         }
451b5da9499SMatthew G. Knepley       }
452b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
453b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2 + cellSize);CHKERRQ(ierr);
454b5da9499SMatthew G. Knepley     }
455b5da9499SMatthew G. Knepley     break;
4562eabf88fSMatthew G. Knepley   case 6:
4572eabf88fSMatthew G. Knepley     /* Hex 3D */
4582eabf88fSMatthew G. Knepley     /* All cells have 6 faces */
4592eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
4602eabf88fSMatthew G. Knepley       for (r = 0; r < 8; ++r) {
4612eabf88fSMatthew G. Knepley         const PetscInt newp = (c - cStart)*8 + r;
4622eabf88fSMatthew G. Knepley 
4632eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 6);CHKERRQ(ierr);
4642eabf88fSMatthew G. Knepley       }
4652eabf88fSMatthew G. Knepley     }
4662eabf88fSMatthew G. Knepley     /* Split faces have 4 edges and the same cells as the parent */
4672eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
4682eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
4692eabf88fSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
4702eabf88fSMatthew G. Knepley         PetscInt       size;
4712eabf88fSMatthew G. Knepley 
4722eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
4732eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
4742eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
4752eabf88fSMatthew G. Knepley       }
4762eabf88fSMatthew G. Knepley     }
4772eabf88fSMatthew G. Knepley     /* Interior faces have 4 edges and 2 cells */
4782eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
4792eabf88fSMatthew G. Knepley       for (r = 0; r < 12; ++r) {
4802eabf88fSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
4812eabf88fSMatthew G. Knepley 
4822eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
4832eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
4842eabf88fSMatthew G. Knepley       }
4852eabf88fSMatthew G. Knepley     }
4862eabf88fSMatthew G. Knepley     /* Split edges have 2 vertices and the same faces as the parent */
4872eabf88fSMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
4882eabf88fSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
4892eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
4902eabf88fSMatthew G. Knepley         PetscInt       size;
4912eabf88fSMatthew G. Knepley 
4922eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
4932eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
4942eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
4952eabf88fSMatthew G. Knepley       }
4962eabf88fSMatthew G. Knepley     }
4972eabf88fSMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells faces */
4982eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
4992eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
5002eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
5012eabf88fSMatthew G. Knepley         PetscInt       size;
5022eabf88fSMatthew G. Knepley 
5032eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
5042eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
5052eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2+size);CHKERRQ(ierr);
5062eabf88fSMatthew G. Knepley       }
5072eabf88fSMatthew G. Knepley     }
5082eabf88fSMatthew G. Knepley     /* Cell edges have 2 vertices and 4 faces */
5092eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
5102eabf88fSMatthew G. Knepley       for (r = 0; r < 6; ++r) {
5112eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
5122eabf88fSMatthew G. Knepley 
5132eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
5142eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
5152eabf88fSMatthew G. Knepley       }
5162eabf88fSMatthew G. Knepley     }
5172eabf88fSMatthew G. Knepley     /* Old vertices have identical supports */
5182eabf88fSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
5192eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
5202eabf88fSMatthew G. Knepley       PetscInt       size;
5212eabf88fSMatthew G. Knepley 
5222eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
5232eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
5242eabf88fSMatthew G. Knepley     }
5252eabf88fSMatthew G. Knepley     /* Edge vertices have 2 + faces supports */
5262eabf88fSMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
5272eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
5282eabf88fSMatthew G. Knepley       PetscInt       size;
5292eabf88fSMatthew G. Knepley 
5302eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
5312eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
5322eabf88fSMatthew G. Knepley     }
5332eabf88fSMatthew G. Knepley     /* Face vertices have 4 + cells supports */
5342eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
5352eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
5362eabf88fSMatthew G. Knepley       PetscInt       size;
5372eabf88fSMatthew G. Knepley 
5382eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
5392eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4 + size);CHKERRQ(ierr);
5402eabf88fSMatthew G. Knepley     }
5412eabf88fSMatthew G. Knepley     /* Cell vertices have 6 supports */
5422eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
5432eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
5442eabf88fSMatthew G. Knepley 
5452eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 6);CHKERRQ(ierr);
5462eabf88fSMatthew G. Knepley     }
5472eabf88fSMatthew G. Knepley     break;
54875d3a19aSMatthew G. Knepley   default:
54975d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
55075d3a19aSMatthew G. Knepley   }
55175d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
55275d3a19aSMatthew G. Knepley }
55375d3a19aSMatthew G. Knepley 
55475d3a19aSMatthew G. Knepley #undef __FUNCT__
55575d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetCones"
55675d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
55775d3a19aSMatthew G. Knepley {
558b5da9499SMatthew G. Knepley   const PetscInt *faces, cellInd[4] = {0, 1, 2, 3};
559b5da9499SMatthew 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;
56075d3a19aSMatthew G. Knepley   PetscInt        maxSupportSize, *supportRef;
56175d3a19aSMatthew G. Knepley   PetscErrorCode  ierr;
56275d3a19aSMatthew G. Knepley 
56375d3a19aSMatthew G. Knepley   PetscFunctionBegin;
56475d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
56575d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
56675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
56775d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
56875d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
56975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
57075d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
57175d3a19aSMatthew G. Knepley   ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr);
57275d3a19aSMatthew G. Knepley   switch (refiner) {
57375d3a19aSMatthew G. Knepley   case 1:
57475d3a19aSMatthew G. Knepley     /* Simplicial 2D */
57575d3a19aSMatthew G. Knepley     /*
57675d3a19aSMatthew G. Knepley      2
57775d3a19aSMatthew G. Knepley      |\
57875d3a19aSMatthew G. Knepley      | \
57975d3a19aSMatthew G. Knepley      |  \
58075d3a19aSMatthew G. Knepley      |   \
58175d3a19aSMatthew G. Knepley      | C  \
58275d3a19aSMatthew G. Knepley      |     \
58375d3a19aSMatthew G. Knepley      |      \
58475d3a19aSMatthew G. Knepley      2---1---1
58575d3a19aSMatthew G. Knepley      |\  D  / \
58675d3a19aSMatthew G. Knepley      | 2   0   \
58775d3a19aSMatthew G. Knepley      |A \ /  B  \
58875d3a19aSMatthew G. Knepley      0---0-------1
58975d3a19aSMatthew G. Knepley      */
59075d3a19aSMatthew G. Knepley     /* All cells have 3 faces */
59175d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
59275d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*4;
59375d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
59475d3a19aSMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
59575d3a19aSMatthew G. Knepley 
59675d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
59775d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
59875d3a19aSMatthew G. Knepley       /* A triangle */
59975d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
60075d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
60175d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
60275d3a19aSMatthew G. Knepley       orntNew[1] = -2;
60375d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
60475d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
60575d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
60675d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
60775d3a19aSMatthew G. Knepley #if 1
60875d3a19aSMatthew 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);
60975d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
61075d3a19aSMatthew 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);
61175d3a19aSMatthew G. Knepley       }
61275d3a19aSMatthew G. Knepley #endif
61375d3a19aSMatthew G. Knepley       /* B triangle */
61475d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
61575d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
61675d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
61775d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
61875d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
61975d3a19aSMatthew G. Knepley       orntNew[2] = -2;
62075d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
62175d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
62275d3a19aSMatthew G. Knepley #if 1
62375d3a19aSMatthew 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);
62475d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
62575d3a19aSMatthew 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);
62675d3a19aSMatthew G. Knepley       }
62775d3a19aSMatthew G. Knepley #endif
62875d3a19aSMatthew G. Knepley       /* C triangle */
62975d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
63075d3a19aSMatthew G. Knepley       orntNew[0] = -2;
63175d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
63275d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
63375d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
63475d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
63575d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
63675d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
63775d3a19aSMatthew G. Knepley #if 1
63875d3a19aSMatthew 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);
63975d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
64075d3a19aSMatthew 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);
64175d3a19aSMatthew G. Knepley       }
64275d3a19aSMatthew G. Knepley #endif
64375d3a19aSMatthew G. Knepley       /* D triangle */
64475d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
64575d3a19aSMatthew G. Knepley       orntNew[0] = 0;
64675d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
64775d3a19aSMatthew G. Knepley       orntNew[1] = 0;
64875d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
64975d3a19aSMatthew G. Knepley       orntNew[2] = 0;
65075d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
65175d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
65275d3a19aSMatthew G. Knepley #if 1
65375d3a19aSMatthew 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);
65475d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
65575d3a19aSMatthew 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);
65675d3a19aSMatthew G. Knepley       }
65775d3a19aSMatthew G. Knepley #endif
65875d3a19aSMatthew G. Knepley     }
65975d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
66075d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
66175d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
66275d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
66375d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
66475d3a19aSMatthew G. Knepley 
66575d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
66675d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
667297d2bf4SMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
66875d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
66975d3a19aSMatthew G. Knepley 
67075d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
67175d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
67275d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
67375d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
67475d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
67575d3a19aSMatthew G. Knepley #if 1
67675d3a19aSMatthew 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);
67775d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
67875d3a19aSMatthew 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);
67975d3a19aSMatthew G. Knepley         }
68075d3a19aSMatthew G. Knepley #endif
68175d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
68275d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
68375d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
68475d3a19aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
68575d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
686297d2bf4SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
68775d3a19aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
68875d3a19aSMatthew G. Knepley             if (cone[c] == f) break;
68975d3a19aSMatthew G. Knepley           }
690297d2bf4SMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
69175d3a19aSMatthew G. Knepley         }
69275d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
69375d3a19aSMatthew G. Knepley #if 1
69475d3a19aSMatthew 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);
69575d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
69675d3a19aSMatthew 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);
69775d3a19aSMatthew G. Knepley         }
69875d3a19aSMatthew G. Knepley #endif
69975d3a19aSMatthew G. Knepley       }
70075d3a19aSMatthew G. Knepley     }
70175d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
70275d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
70375d3a19aSMatthew G. Knepley       const PetscInt *cone;
70475d3a19aSMatthew G. Knepley 
70575d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
70675d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
70775d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
70875d3a19aSMatthew G. Knepley         PetscInt       coneNew[2];
70975d3a19aSMatthew G. Knepley         PetscInt       supportNew[2];
71075d3a19aSMatthew G. Knepley 
71175d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
71275d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
71375d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
71475d3a19aSMatthew G. Knepley #if 1
71575d3a19aSMatthew 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);
71675d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
71775d3a19aSMatthew 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);
71875d3a19aSMatthew G. Knepley         }
71975d3a19aSMatthew G. Knepley #endif
72075d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + (r+1)%3;
72175d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + 3;
72275d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
72375d3a19aSMatthew G. Knepley #if 1
72475d3a19aSMatthew 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);
72575d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
72675d3a19aSMatthew 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);
72775d3a19aSMatthew G. Knepley         }
72875d3a19aSMatthew G. Knepley #endif
72975d3a19aSMatthew G. Knepley       }
73075d3a19aSMatthew G. Knepley     }
73175d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
73275d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
73375d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
73475d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
73575d3a19aSMatthew G. Knepley       PetscInt        size, s;
73675d3a19aSMatthew G. Knepley 
73775d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
73875d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
73975d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
74075d3a19aSMatthew G. Knepley         PetscInt r = 0;
74175d3a19aSMatthew G. Knepley 
74275d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
74375d3a19aSMatthew G. Knepley         if (cone[1] == v) r = 1;
74475d3a19aSMatthew G. Knepley         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
74575d3a19aSMatthew G. Knepley       }
74675d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
74775d3a19aSMatthew G. Knepley #if 1
74875d3a19aSMatthew 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);
74975d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
75075d3a19aSMatthew 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);
75175d3a19aSMatthew G. Knepley       }
75275d3a19aSMatthew G. Knepley #endif
75375d3a19aSMatthew G. Knepley     }
75475d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells*2 supports */
75575d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
75675d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
75775d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
75875d3a19aSMatthew G. Knepley       PetscInt        size, s;
75975d3a19aSMatthew G. Knepley 
76075d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
76175d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
76275d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
76375d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
76475d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
76575d3a19aSMatthew G. Knepley         PetscInt r = 0;
76675d3a19aSMatthew G. Knepley 
76775d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
76875d3a19aSMatthew G. Knepley         if      (cone[1] == f) r = 1;
76975d3a19aSMatthew G. Knepley         else if (cone[2] == f) r = 2;
77075d3a19aSMatthew G. Knepley         supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
77175d3a19aSMatthew G. Knepley         supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
77275d3a19aSMatthew G. Knepley       }
77375d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
77475d3a19aSMatthew G. Knepley #if 1
77575d3a19aSMatthew 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);
77675d3a19aSMatthew G. Knepley       for (p = 0; p < 2+size*2; ++p) {
77775d3a19aSMatthew 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);
77875d3a19aSMatthew G. Knepley       }
77975d3a19aSMatthew G. Knepley #endif
78075d3a19aSMatthew G. Knepley     }
78175d3a19aSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
78275d3a19aSMatthew G. Knepley     break;
78375d3a19aSMatthew G. Knepley   case 2:
78475d3a19aSMatthew G. Knepley     /* Hex 2D */
78575d3a19aSMatthew G. Knepley     /*
78675d3a19aSMatthew G. Knepley      3---------2---------2
78775d3a19aSMatthew G. Knepley      |         |         |
78875d3a19aSMatthew G. Knepley      |    D    2    C    |
78975d3a19aSMatthew G. Knepley      |         |         |
79075d3a19aSMatthew G. Knepley      3----3----0----1----1
79175d3a19aSMatthew G. Knepley      |         |         |
79275d3a19aSMatthew G. Knepley      |    A    0    B    |
79375d3a19aSMatthew G. Knepley      |         |         |
79475d3a19aSMatthew G. Knepley      0---------0---------1
79575d3a19aSMatthew G. Knepley      */
79675d3a19aSMatthew G. Knepley     /* All cells have 4 faces */
79775d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
79875d3a19aSMatthew G. Knepley       const PetscInt  newp = (c - cStart)*4;
79975d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
80075d3a19aSMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
80175d3a19aSMatthew G. Knepley 
80275d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
80375d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
80475d3a19aSMatthew G. Knepley       /* A quad */
80575d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
80675d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
80775d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
80875d3a19aSMatthew G. Knepley       orntNew[1] = 0;
80975d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
81075d3a19aSMatthew G. Knepley       orntNew[2] = -2;
81175d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
81275d3a19aSMatthew G. Knepley       orntNew[3] = ornt[3];
81375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
81475d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
81575d3a19aSMatthew G. Knepley #if 1
81675d3a19aSMatthew 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);
81775d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
81875d3a19aSMatthew 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);
81975d3a19aSMatthew G. Knepley       }
82075d3a19aSMatthew G. Knepley #endif
82175d3a19aSMatthew G. Knepley       /* B quad */
82275d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
82375d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
82475d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
82575d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
82675d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
82775d3a19aSMatthew G. Knepley       orntNew[2] = 0;
82875d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
82975d3a19aSMatthew G. Knepley       orntNew[3] = -2;
83075d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
83175d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
83275d3a19aSMatthew G. Knepley #if 1
83375d3a19aSMatthew 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);
83475d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
83575d3a19aSMatthew 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);
83675d3a19aSMatthew G. Knepley       }
83775d3a19aSMatthew G. Knepley #endif
83875d3a19aSMatthew G. Knepley       /* C quad */
83975d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
84075d3a19aSMatthew G. Knepley       orntNew[0] = -2;
84175d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
84275d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
84375d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
84475d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
84575d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
84675d3a19aSMatthew G. Knepley       orntNew[3] = 0;
84775d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
84875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
84975d3a19aSMatthew G. Knepley #if 1
85075d3a19aSMatthew 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);
85175d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
85275d3a19aSMatthew 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);
85375d3a19aSMatthew G. Knepley       }
85475d3a19aSMatthew G. Knepley #endif
85575d3a19aSMatthew G. Knepley       /* D quad */
85675d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
85775d3a19aSMatthew G. Knepley       orntNew[0] = 0;
85875d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
85975d3a19aSMatthew G. Knepley       orntNew[1] = -2;
86075d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
86175d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
86275d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
86375d3a19aSMatthew G. Knepley       orntNew[3] = ornt[3];
86475d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
86575d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
86675d3a19aSMatthew G. Knepley #if 1
86775d3a19aSMatthew 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);
86875d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
86975d3a19aSMatthew 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);
87075d3a19aSMatthew G. Knepley       }
87175d3a19aSMatthew G. Knepley #endif
87275d3a19aSMatthew G. Knepley     }
87375d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
87475d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
87575d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
87675d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
87775d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
87875d3a19aSMatthew G. Knepley 
87975d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
88075d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
881455d6cd4SMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
88275d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
88375d3a19aSMatthew G. Knepley 
88475d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
88575d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
88675d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
88775d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
88875d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
88975d3a19aSMatthew G. Knepley #if 1
89075d3a19aSMatthew 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);
89175d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
89275d3a19aSMatthew 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);
89375d3a19aSMatthew G. Knepley         }
89475d3a19aSMatthew G. Knepley #endif
89575d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
89675d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
89775d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
89875d3a19aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
89975d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
900455d6cd4SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
90175d3a19aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
90275d3a19aSMatthew G. Knepley             if (cone[c] == f) break;
90375d3a19aSMatthew G. Knepley           }
904455d6cd4SMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
90575d3a19aSMatthew G. Knepley         }
90675d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
90775d3a19aSMatthew G. Knepley #if 1
90875d3a19aSMatthew 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);
90975d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
91075d3a19aSMatthew 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);
91175d3a19aSMatthew G. Knepley         }
91275d3a19aSMatthew G. Knepley #endif
91375d3a19aSMatthew G. Knepley       }
91475d3a19aSMatthew G. Knepley     }
91575d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
91675d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
91775d3a19aSMatthew G. Knepley       const PetscInt *cone;
91875d3a19aSMatthew G. Knepley       PetscInt        coneNew[2], supportNew[2];
91975d3a19aSMatthew G. Knepley 
92075d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
92175d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
92275d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
92375d3a19aSMatthew G. Knepley 
92475d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
92575d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
92675d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
92775d3a19aSMatthew G. Knepley #if 1
92875d3a19aSMatthew 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);
92975d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
93075d3a19aSMatthew 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);
93175d3a19aSMatthew G. Knepley         }
93275d3a19aSMatthew G. Knepley #endif
93375d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + r;
93475d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + (r+1)%4;
93575d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
93675d3a19aSMatthew G. Knepley #if 1
93775d3a19aSMatthew 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);
93875d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
93975d3a19aSMatthew 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);
94075d3a19aSMatthew G. Knepley         }
94175d3a19aSMatthew G. Knepley #endif
94275d3a19aSMatthew G. Knepley       }
94375d3a19aSMatthew G. Knepley     }
94475d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
94575d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
94675d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
94775d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
94875d3a19aSMatthew G. Knepley       PetscInt        size, s;
94975d3a19aSMatthew G. Knepley 
95075d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
95175d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
95275d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
95375d3a19aSMatthew G. Knepley         PetscInt r = 0;
95475d3a19aSMatthew G. Knepley 
95575d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
95675d3a19aSMatthew G. Knepley         if (cone[1] == v) r = 1;
95775d3a19aSMatthew G. Knepley         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
95875d3a19aSMatthew G. Knepley       }
95975d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
96075d3a19aSMatthew G. Knepley #if 1
96175d3a19aSMatthew 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);
96275d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
96375d3a19aSMatthew 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);
96475d3a19aSMatthew G. Knepley       }
96575d3a19aSMatthew G. Knepley #endif
96675d3a19aSMatthew G. Knepley     }
96775d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells supports */
96875d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
96975d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
97075d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
97175d3a19aSMatthew G. Knepley       PetscInt        size, s;
97275d3a19aSMatthew G. Knepley 
97375d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
97475d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
97575d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
97675d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
97775d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
97875d3a19aSMatthew G. Knepley         PetscInt r = 0;
97975d3a19aSMatthew G. Knepley 
98075d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
98175d3a19aSMatthew G. Knepley         if      (cone[1] == f) r = 1;
98275d3a19aSMatthew G. Knepley         else if (cone[2] == f) r = 2;
98375d3a19aSMatthew G. Knepley         else if (cone[3] == f) r = 3;
98475d3a19aSMatthew G. Knepley         supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r;
98575d3a19aSMatthew G. Knepley       }
98675d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
98775d3a19aSMatthew G. Knepley #if 1
98875d3a19aSMatthew 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);
98975d3a19aSMatthew G. Knepley       for (p = 0; p < 2+size; ++p) {
99075d3a19aSMatthew 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);
99175d3a19aSMatthew G. Knepley       }
99275d3a19aSMatthew G. Knepley #endif
99375d3a19aSMatthew G. Knepley     }
99475d3a19aSMatthew G. Knepley     /* Cell vertices have 4 supports */
99575d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
99675d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
99775d3a19aSMatthew G. Knepley       PetscInt       supportNew[4];
99875d3a19aSMatthew G. Knepley 
99975d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
100075d3a19aSMatthew G. Knepley         supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
100175d3a19aSMatthew G. Knepley       }
100275d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
100375d3a19aSMatthew G. Knepley     }
1004da00770fSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
100575d3a19aSMatthew G. Knepley     break;
100675d3a19aSMatthew G. Knepley   case 3:
100775d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
100875d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
100975d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
101075d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
101175d3a19aSMatthew G. Knepley     /* Interior cells have 3 faces */
101275d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
101375d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*4;
101475d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
101575d3a19aSMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
101675d3a19aSMatthew G. Knepley 
101775d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
101875d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
101975d3a19aSMatthew G. Knepley       /* A triangle */
102075d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
102175d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
102275d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
102375d3a19aSMatthew G. Knepley       orntNew[1] = -2;
102475d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
102575d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
102675d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
102775d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
102875d3a19aSMatthew G. Knepley #if 1
102975d3a19aSMatthew 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);
103075d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
103175d3a19aSMatthew 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);
103275d3a19aSMatthew G. Knepley       }
103375d3a19aSMatthew G. Knepley #endif
103475d3a19aSMatthew G. Knepley       /* B triangle */
103575d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
103675d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
103775d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
103875d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
103975d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
104075d3a19aSMatthew G. Knepley       orntNew[2] = -2;
104175d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
104275d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
104375d3a19aSMatthew G. Knepley #if 1
104475d3a19aSMatthew 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);
104575d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
104675d3a19aSMatthew 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);
104775d3a19aSMatthew G. Knepley       }
104875d3a19aSMatthew G. Knepley #endif
104975d3a19aSMatthew G. Knepley       /* C triangle */
105075d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
105175d3a19aSMatthew G. Knepley       orntNew[0] = -2;
105275d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
105375d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
105475d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
105575d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
105675d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
105775d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
105875d3a19aSMatthew G. Knepley #if 1
105975d3a19aSMatthew 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);
106075d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
106175d3a19aSMatthew 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);
106275d3a19aSMatthew G. Knepley       }
106375d3a19aSMatthew G. Knepley #endif
106475d3a19aSMatthew G. Knepley       /* D triangle */
106575d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
106675d3a19aSMatthew G. Knepley       orntNew[0] = 0;
106775d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
106875d3a19aSMatthew G. Knepley       orntNew[1] = 0;
106975d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
107075d3a19aSMatthew G. Knepley       orntNew[2] = 0;
107175d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
107275d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
107375d3a19aSMatthew G. Knepley #if 1
107475d3a19aSMatthew 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);
107575d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
107675d3a19aSMatthew 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);
107775d3a19aSMatthew G. Knepley       }
107875d3a19aSMatthew G. Knepley #endif
107975d3a19aSMatthew G. Knepley     }
108075d3a19aSMatthew G. Knepley     /*
108175d3a19aSMatthew G. Knepley      2----3----3
108275d3a19aSMatthew G. Knepley      |         |
108375d3a19aSMatthew G. Knepley      |    B    |
108475d3a19aSMatthew G. Knepley      |         |
108575d3a19aSMatthew G. Knepley      0----4--- 1
108675d3a19aSMatthew G. Knepley      |         |
108775d3a19aSMatthew G. Knepley      |    A    |
108875d3a19aSMatthew G. Knepley      |         |
108975d3a19aSMatthew G. Knepley      0----2----1
109075d3a19aSMatthew G. Knepley      */
109175d3a19aSMatthew G. Knepley     /* Hybrid cells have 4 faces */
109275d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
109375d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
109475d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
109575d3a19aSMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
109675d3a19aSMatthew G. Knepley 
109775d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
109875d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
109975d3a19aSMatthew G. Knepley       /* A quad */
110075d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
110175d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
110275d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
110375d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
110475d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax);
110575d3a19aSMatthew G. Knepley       orntNew[2] = 0;
110675d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
110775d3a19aSMatthew G. Knepley       orntNew[3] = 0;
110875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
110975d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
111075d3a19aSMatthew G. Knepley #if 1
111175d3a19aSMatthew 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);
111275d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
111375d3a19aSMatthew 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);
111475d3a19aSMatthew G. Knepley       }
111575d3a19aSMatthew G. Knepley #endif
111675d3a19aSMatthew G. Knepley       /* B quad */
111775d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
111875d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
111975d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
112075d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
112175d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
112275d3a19aSMatthew G. Knepley       orntNew[2] = 0;
112375d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax);
112475d3a19aSMatthew G. Knepley       orntNew[3] = 0;
112575d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
112675d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
112775d3a19aSMatthew G. Knepley #if 1
112875d3a19aSMatthew 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);
112975d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
113075d3a19aSMatthew 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);
113175d3a19aSMatthew G. Knepley       }
113275d3a19aSMatthew G. Knepley #endif
113375d3a19aSMatthew G. Knepley     }
113475d3a19aSMatthew G. Knepley     /* Interior split faces have 2 vertices and the same cells as the parent */
113575d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
113675d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
113775d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
113875d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
113975d3a19aSMatthew G. Knepley 
114075d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
114175d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
1142297d2bf4SMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
114375d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
114475d3a19aSMatthew G. Knepley 
114575d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
114675d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
114775d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
114875d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
114975d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
115075d3a19aSMatthew G. Knepley #if 1
115175d3a19aSMatthew 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);
115275d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
115375d3a19aSMatthew 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);
115475d3a19aSMatthew G. Knepley         }
115575d3a19aSMatthew G. Knepley #endif
115675d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
115775d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
115875d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
115975d3a19aSMatthew G. Knepley           if (support[s] >= cMax) {
116075d3a19aSMatthew G. Knepley             supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
116175d3a19aSMatthew G. Knepley           } else {
116275d3a19aSMatthew G. Knepley             ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
116375d3a19aSMatthew G. Knepley             ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1164297d2bf4SMatthew G. Knepley             ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
116575d3a19aSMatthew G. Knepley             for (c = 0; c < coneSize; ++c) {
116675d3a19aSMatthew G. Knepley               if (cone[c] == f) break;
116775d3a19aSMatthew G. Knepley             }
1168297d2bf4SMatthew G. Knepley             supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
116975d3a19aSMatthew G. Knepley           }
117075d3a19aSMatthew G. Knepley         }
117175d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
117275d3a19aSMatthew G. Knepley #if 1
117375d3a19aSMatthew 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);
117475d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
117575d3a19aSMatthew 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);
117675d3a19aSMatthew G. Knepley         }
117775d3a19aSMatthew G. Knepley #endif
117875d3a19aSMatthew G. Knepley       }
117975d3a19aSMatthew G. Knepley     }
118075d3a19aSMatthew G. Knepley     /* Interior cell faces have 2 vertices and 2 cells */
118175d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
118275d3a19aSMatthew G. Knepley       const PetscInt *cone;
118375d3a19aSMatthew G. Knepley 
118475d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
118575d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
118675d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
118775d3a19aSMatthew G. Knepley         PetscInt       coneNew[2];
118875d3a19aSMatthew G. Knepley         PetscInt       supportNew[2];
118975d3a19aSMatthew G. Knepley 
119075d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
119175d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
119275d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
119375d3a19aSMatthew G. Knepley #if 1
119475d3a19aSMatthew 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);
119575d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
119675d3a19aSMatthew 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);
119775d3a19aSMatthew G. Knepley         }
119875d3a19aSMatthew G. Knepley #endif
119975d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + (r+1)%3;
120075d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + 3;
120175d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
120275d3a19aSMatthew G. Knepley #if 1
120375d3a19aSMatthew 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);
120475d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
120575d3a19aSMatthew 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);
120675d3a19aSMatthew G. Knepley         }
120775d3a19aSMatthew G. Knepley #endif
120875d3a19aSMatthew G. Knepley       }
120975d3a19aSMatthew G. Knepley     }
121075d3a19aSMatthew G. Knepley     /* Interior hybrid faces have 2 vertices and the same cells */
121175d3a19aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
121275d3a19aSMatthew G. Knepley       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
121375d3a19aSMatthew G. Knepley       const PetscInt *cone;
121475d3a19aSMatthew G. Knepley       const PetscInt *support;
121575d3a19aSMatthew G. Knepley       PetscInt        coneNew[2];
121675d3a19aSMatthew G. Knepley       PetscInt        supportNew[2];
121775d3a19aSMatthew G. Knepley       PetscInt        size, s, r;
121875d3a19aSMatthew G. Knepley 
121975d3a19aSMatthew G. Knepley       ierr       = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
122075d3a19aSMatthew G. Knepley       coneNew[0] = vStartNew + (cone[0] - vStart);
122175d3a19aSMatthew G. Knepley       coneNew[1] = vStartNew + (cone[1] - vStart);
122275d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
122375d3a19aSMatthew G. Knepley #if 1
122475d3a19aSMatthew 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);
122575d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
122675d3a19aSMatthew 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);
122775d3a19aSMatthew G. Knepley       }
122875d3a19aSMatthew G. Knepley #endif
122975d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
123075d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
123175d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
123275d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
123375d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r) {
123475d3a19aSMatthew G. Knepley           if (cone[r+2] == f) break;
123575d3a19aSMatthew G. Knepley         }
123675d3a19aSMatthew G. Knepley         supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
123775d3a19aSMatthew G. Knepley       }
123875d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
123975d3a19aSMatthew G. Knepley #if 1
124075d3a19aSMatthew 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);
124175d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
124275d3a19aSMatthew 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);
124375d3a19aSMatthew G. Knepley       }
124475d3a19aSMatthew G. Knepley #endif
124575d3a19aSMatthew G. Knepley     }
124675d3a19aSMatthew G. Knepley     /* Cell hybrid faces have 2 vertices and 2 cells */
124775d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
124875d3a19aSMatthew G. Knepley       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
124975d3a19aSMatthew G. Knepley       const PetscInt *cone;
125075d3a19aSMatthew G. Knepley       PetscInt        coneNew[2];
125175d3a19aSMatthew G. Knepley       PetscInt        supportNew[2];
125275d3a19aSMatthew G. Knepley 
125375d3a19aSMatthew G. Knepley       ierr       = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
125475d3a19aSMatthew G. Knepley       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
125575d3a19aSMatthew G. Knepley       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
125675d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
125775d3a19aSMatthew G. Knepley #if 1
125875d3a19aSMatthew 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);
125975d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
126075d3a19aSMatthew 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);
126175d3a19aSMatthew G. Knepley       }
126275d3a19aSMatthew G. Knepley #endif
126375d3a19aSMatthew G. Knepley       supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
126475d3a19aSMatthew G. Knepley       supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
126575d3a19aSMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
126675d3a19aSMatthew G. Knepley #if 1
126775d3a19aSMatthew 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);
126875d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
126975d3a19aSMatthew 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);
127075d3a19aSMatthew G. Knepley       }
127175d3a19aSMatthew G. Knepley #endif
127275d3a19aSMatthew G. Knepley     }
127375d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
127475d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
127575d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
127675d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
127775d3a19aSMatthew G. Knepley       PetscInt        size, s;
127875d3a19aSMatthew G. Knepley 
127975d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
128075d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
128175d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
128275d3a19aSMatthew G. Knepley         if (support[s] >= fMax) {
128375d3a19aSMatthew G. Knepley           supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax);
128475d3a19aSMatthew G. Knepley         } else {
128575d3a19aSMatthew G. Knepley           PetscInt r = 0;
128675d3a19aSMatthew G. Knepley 
128775d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
128875d3a19aSMatthew G. Knepley           if (cone[1] == v) r = 1;
128975d3a19aSMatthew G. Knepley           supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
129075d3a19aSMatthew G. Knepley         }
129175d3a19aSMatthew G. Knepley       }
129275d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
129375d3a19aSMatthew G. Knepley #if 1
129475d3a19aSMatthew 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);
129575d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
129675d3a19aSMatthew 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);
129775d3a19aSMatthew G. Knepley       }
129875d3a19aSMatthew G. Knepley #endif
129975d3a19aSMatthew G. Knepley     }
130075d3a19aSMatthew G. Knepley     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
130175d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
130275d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
130375d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
130475d3a19aSMatthew G. Knepley       PetscInt        size, newSize = 2, s;
130575d3a19aSMatthew G. Knepley 
130675d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
130775d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
130875d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
130975d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
131075d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
131175d3a19aSMatthew G. Knepley         PetscInt r = 0;
131275d3a19aSMatthew G. Knepley 
131375d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
131475d3a19aSMatthew G. Knepley         if (support[s] >= cMax) {
131575d3a19aSMatthew G. Knepley           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax);
131675d3a19aSMatthew G. Knepley 
131775d3a19aSMatthew G. Knepley           newSize += 1;
131875d3a19aSMatthew G. Knepley         } else {
131975d3a19aSMatthew G. Knepley           if      (cone[1] == f) r = 1;
132075d3a19aSMatthew G. Knepley           else if (cone[2] == f) r = 2;
132175d3a19aSMatthew G. Knepley           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
132275d3a19aSMatthew G. Knepley           supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r;
132375d3a19aSMatthew G. Knepley 
132475d3a19aSMatthew G. Knepley           newSize += 2;
132575d3a19aSMatthew G. Knepley         }
132675d3a19aSMatthew G. Knepley       }
132775d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
132875d3a19aSMatthew G. Knepley #if 1
132975d3a19aSMatthew 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);
133075d3a19aSMatthew G. Knepley       for (p = 0; p < newSize; ++p) {
133175d3a19aSMatthew 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);
133275d3a19aSMatthew G. Knepley       }
133375d3a19aSMatthew G. Knepley #endif
133475d3a19aSMatthew G. Knepley     }
133575d3a19aSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
133675d3a19aSMatthew G. Knepley     break;
1337b5da9499SMatthew G. Knepley   case 5:
1338b5da9499SMatthew G. Knepley     /* Simplicial 3D */
1339b5da9499SMatthew G. Knepley     /* All cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
1340b5da9499SMatthew G. Knepley     ierr = DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);CHKERRQ(ierr);
1341b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1342b5da9499SMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*8;
1343b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt;
1344b5da9499SMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
1345b5da9499SMatthew G. Knepley 
1346b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1347b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1348b5da9499SMatthew G. Knepley       /* A tetrahedron: {0, a, c, d} */
1349518a8359SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
1350b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1351518a8359SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
1352b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1353518a8359SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
1354b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1355b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
1356b5da9499SMatthew G. Knepley       orntNew[3] = 0;
1357b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1358b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1359b5da9499SMatthew G. Knepley #if 1
1360b5da9499SMatthew 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);
1361b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1362b5da9499SMatthew 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);
1363b5da9499SMatthew G. Knepley       }
1364b5da9499SMatthew G. Knepley #endif
1365b5da9499SMatthew G. Knepley       /* B tetrahedron: {a, 1, b, e} */
1366518a8359SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
1367b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1368518a8359SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
1369b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1370b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
1371b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1372518a8359SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
1373b5da9499SMatthew G. Knepley       orntNew[3] = ornt[3];
1374b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1375b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1376b5da9499SMatthew G. Knepley #if 1
1377b5da9499SMatthew 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);
1378b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1379b5da9499SMatthew 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);
1380b5da9499SMatthew G. Knepley       }
1381b5da9499SMatthew G. Knepley #endif
1382b5da9499SMatthew G. Knepley       /* C tetrahedron: {c, b, 2, f} */
1383518a8359SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
1384b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1385b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
1386b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1387518a8359SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
1388b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1389518a8359SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
1390b5da9499SMatthew G. Knepley       orntNew[3] = ornt[3];
1391b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1392b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1393b5da9499SMatthew G. Knepley #if 1
1394b5da9499SMatthew 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);
1395b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1396b5da9499SMatthew 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);
1397b5da9499SMatthew G. Knepley       }
1398b5da9499SMatthew G. Knepley #endif
1399b5da9499SMatthew G. Knepley       /* D tetrahedron: {d, e, f, 3} */
1400b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
1401b5da9499SMatthew G. Knepley       orntNew[0] = 0;
1402518a8359SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
1403b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1404518a8359SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
1405b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1406518a8359SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
1407b5da9499SMatthew G. Knepley       orntNew[3] = ornt[3];
1408b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
1409b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
1410b5da9499SMatthew G. Knepley #if 1
1411b5da9499SMatthew 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);
1412b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1413b5da9499SMatthew 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);
1414b5da9499SMatthew G. Knepley       }
1415b5da9499SMatthew G. Knepley #endif
1416b5da9499SMatthew G. Knepley       /* A' tetrahedron: {d, a, c, f} */
1417b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
1418b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1419b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
1420b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1421b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + 3;
1422b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -((-(ornt[2]+1)+2)%3+1) : (ornt[2]+2)%3;
1423b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
1424b5da9499SMatthew G. Knepley       orntNew[3] = 0;
1425b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
1426b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
1427b5da9499SMatthew G. Knepley #if 1
1428b5da9499SMatthew 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);
1429b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1430b5da9499SMatthew 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);
1431b5da9499SMatthew G. Knepley       }
1432b5da9499SMatthew G. Knepley #endif
1433b5da9499SMatthew G. Knepley       /* B' tetrahedron: {e, b, a, f} */
1434b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
1435b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1436b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[3] - fStart)*4 + 3;
1437b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -((-(ornt[3]+1)+1)%3+1) : (ornt[3]+1)%3;
1438b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
1439b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1440b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
1441b5da9499SMatthew G. Knepley       orntNew[3] = 0;
1442b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
1443b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
1444b5da9499SMatthew G. Knepley #if 1
1445b5da9499SMatthew 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);
1446b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1447b5da9499SMatthew 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);
1448b5da9499SMatthew G. Knepley       }
1449b5da9499SMatthew G. Knepley #endif
1450b5da9499SMatthew G. Knepley       /* C' tetrahedron: {b, f, c, a} */
1451b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
1452b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1453b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
1454b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1455b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[0] - fStart)*4 + 3;
1456b5da9499SMatthew G. Knepley       orntNew[2] = ornt[0] < 0 ? (-(ornt[0]+1)+1)%3 : -((ornt[0]+1)%3+1);
1457b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
1458b5da9499SMatthew G. Knepley       orntNew[3] = -1;
1459b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
1460b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
1461b5da9499SMatthew G. Knepley #if 1
1462b5da9499SMatthew 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);
1463b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1464b5da9499SMatthew 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);
1465b5da9499SMatthew G. Knepley       }
1466b5da9499SMatthew G. Knepley #endif
1467b5da9499SMatthew G. Knepley       /* D' tetrahedron: {f, e, d, a} */
1468b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
1469b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1470b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
1471b5da9499SMatthew G. Knepley       orntNew[1] = -3;
1472b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
1473b5da9499SMatthew G. Knepley       orntNew[2] = -2;
1474b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[1] - fStart)*4 + 3;
1475b5da9499SMatthew G. Knepley       orntNew[3] = ornt[2];
1476b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
1477b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
1478b5da9499SMatthew G. Knepley #if 1
1479b5da9499SMatthew 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);
1480b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1481b5da9499SMatthew 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);
1482b5da9499SMatthew G. Knepley       }
1483b5da9499SMatthew G. Knepley #endif
1484b5da9499SMatthew G. Knepley     }
1485b5da9499SMatthew G. Knepley     /* Split faces have 3 edges and the same cells as the parent */
1486b5da9499SMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
1487b5da9499SMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
1488b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
1489b5da9499SMatthew G. Knepley       const PetscInt  newp = fStartNew + (f - fStart)*4;
1490b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt, *support;
1491b5da9499SMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3], coneSize, supportSize, s;
1492b5da9499SMatthew G. Knepley 
1493b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1494b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
1495b5da9499SMatthew G. Knepley       /* A triangle */
1496b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
1497b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1498b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
1499b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1500b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
1501b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1502b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1503b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1504b5da9499SMatthew G. Knepley #if 1
1505b5da9499SMatthew 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);
1506b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1507b5da9499SMatthew 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);
1508b5da9499SMatthew G. Knepley       }
1509b5da9499SMatthew G. Knepley #endif
1510b5da9499SMatthew G. Knepley       /* B triangle */
1511b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
1512b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1513b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
1514b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1515b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
1516b5da9499SMatthew G. Knepley       orntNew[2] = -2;
1517b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1518b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1519b5da9499SMatthew G. Knepley #if 1
1520b5da9499SMatthew 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);
1521b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1522b5da9499SMatthew 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);
1523b5da9499SMatthew G. Knepley       }
1524b5da9499SMatthew G. Knepley #endif
1525b5da9499SMatthew G. Knepley       /* C triangle */
1526b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
1527b5da9499SMatthew G. Knepley       orntNew[0] = -2;
1528b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
1529b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1530b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
1531b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1532b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1533b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1534b5da9499SMatthew G. Knepley #if 1
1535b5da9499SMatthew 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);
1536b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1537b5da9499SMatthew 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);
1538b5da9499SMatthew G. Knepley       }
1539b5da9499SMatthew G. Knepley #endif
1540b5da9499SMatthew G. Knepley       /* D triangle */
1541b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
1542b5da9499SMatthew G. Knepley       orntNew[0] = 0;
1543b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
1544b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1545b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
1546b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1547b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
1548b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
1549b5da9499SMatthew G. Knepley #if 1
1550b5da9499SMatthew 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);
1551b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1552b5da9499SMatthew 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);
1553b5da9499SMatthew G. Knepley       }
1554b5da9499SMatthew G. Knepley #endif
1555b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1556b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1557b5da9499SMatthew G. Knepley       for (r = 0; r < 4; ++r) {
1558b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
1559b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1560b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1561b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1562b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
1563b5da9499SMatthew G. Knepley             if (cone[c] == f) break;
1564b5da9499SMatthew G. Knepley           }
1565b5da9499SMatthew 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]));
1566b5da9499SMatthew G. Knepley         }
1567b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp+r, supportRef);CHKERRQ(ierr);
1568b5da9499SMatthew G. Knepley #if 1
1569b5da9499SMatthew 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);
1570b5da9499SMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
1571b5da9499SMatthew 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);
1572b5da9499SMatthew G. Knepley         }
1573b5da9499SMatthew G. Knepley #endif
1574b5da9499SMatthew G. Knepley       }
1575b5da9499SMatthew G. Knepley     }
1576b5da9499SMatthew G. Knepley     /* Interior faces have 3 edges and 2 cells */
1577b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1578b5da9499SMatthew G. Knepley       PetscInt        newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8;
1579b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt;
1580b5da9499SMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
1581b5da9499SMatthew G. Knepley       PetscInt        supportNew[2];
1582b5da9499SMatthew G. Knepley 
1583b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1584b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1585b5da9499SMatthew G. Knepley       /* Face A: {c, a, d} */
1586b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+0)%3 : (ornt[0]+2)%3);
1587b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1588b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+0)%3 : (ornt[1]+2)%3);
1589b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1] < 0 ? -2 : 0;
1590b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+0)%3 : (ornt[2]+2)%3);
1591b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -2 : 0;
1592b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1593b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1594b5da9499SMatthew G. Knepley #if 1
1595b5da9499SMatthew 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);
1596b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1597b5da9499SMatthew 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);
1598b5da9499SMatthew G. Knepley       }
1599b5da9499SMatthew G. Knepley #endif
1600b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0;
1601b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 0+4;
1602b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1603b5da9499SMatthew G. Knepley #if 1
1604b5da9499SMatthew 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);
1605b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1606b5da9499SMatthew 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);
1607b5da9499SMatthew G. Knepley       }
1608b5da9499SMatthew G. Knepley #endif
1609b5da9499SMatthew G. Knepley       ++newp;
1610b5da9499SMatthew G. Knepley       /* Face B: {a, b, e} */
1611b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+2)%3 : (ornt[0]+0)%3);
1612b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1613b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+2)%3 : (ornt[3]+0)%3);
1614b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1615b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+1)%3 : (ornt[1]+1)%3);
1616b5da9499SMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? -2 : 0;
1617b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1618b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1619b5da9499SMatthew G. Knepley #if 1
1620b5da9499SMatthew 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);
1621b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1622b5da9499SMatthew 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);
1623b5da9499SMatthew G. Knepley       }
1624b5da9499SMatthew G. Knepley #endif
1625b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1;
1626b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 1+4;
1627b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1628b5da9499SMatthew G. Knepley #if 1
1629b5da9499SMatthew 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);
1630b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1631b5da9499SMatthew 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);
1632b5da9499SMatthew G. Knepley       }
1633b5da9499SMatthew G. Knepley #endif
1634b5da9499SMatthew G. Knepley       ++newp;
1635b5da9499SMatthew G. Knepley       /* Face C: {c, f, b} */
1636b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+2)%3 : (ornt[2]+0)%3);
1637b5da9499SMatthew G. Knepley       orntNew[0] = ornt[2] < 0 ? -2 : 0;
1638b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+0)%3 : (ornt[3]+2)%3);
1639b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1640b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+1)%3 : (ornt[0]+1)%3);
1641b5da9499SMatthew G. Knepley       orntNew[2] = ornt[0] < 0 ? -2 : 0;
1642b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1643b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1644b5da9499SMatthew G. Knepley #if 1
1645b5da9499SMatthew 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);
1646b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1647b5da9499SMatthew 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);
1648b5da9499SMatthew G. Knepley       }
1649b5da9499SMatthew G. Knepley #endif
1650b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 2;
1651b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
1652b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1653b5da9499SMatthew G. Knepley #if 1
1654b5da9499SMatthew 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);
1655b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1656b5da9499SMatthew 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);
1657b5da9499SMatthew G. Knepley       }
1658b5da9499SMatthew G. Knepley #endif
1659b5da9499SMatthew G. Knepley       ++newp;
1660b5da9499SMatthew G. Knepley       /* Face D: {d, e, f} */
1661b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+2)%3 : (ornt[1]+0)%3);
1662b5da9499SMatthew G. Knepley       orntNew[0] = ornt[1] < 0 ? -2 : 0;
1663b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+1)%3 : (ornt[3]+1)%3);
1664b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1665b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+1)%3 : (ornt[2]+1)%3);
1666b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -2 : 0;
1667b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1668b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1669b5da9499SMatthew G. Knepley #if 1
1670b5da9499SMatthew 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);
1671b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1672b5da9499SMatthew 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);
1673b5da9499SMatthew G. Knepley       }
1674b5da9499SMatthew G. Knepley #endif
1675b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 3;
1676b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
1677b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1678b5da9499SMatthew G. Knepley #if 1
1679b5da9499SMatthew 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);
1680b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1681b5da9499SMatthew 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);
1682b5da9499SMatthew G. Knepley       }
1683b5da9499SMatthew G. Knepley #endif
1684b5da9499SMatthew G. Knepley       ++newp;
1685b5da9499SMatthew G. Knepley       /* Face E: {d, f, a} */
1686b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+1)%3 : (ornt[2]+1)%3);
1687b5da9499SMatthew G. Knepley       orntNew[0] = ornt[2] < 0 ? 0 : -2;
1688b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1689b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1690b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+0)%3 : (ornt[1]+2)%3);
1691b5da9499SMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? -2 : 0;
1692b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1693b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1694b5da9499SMatthew G. Knepley #if 1
1695b5da9499SMatthew 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);
1696b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1697b5da9499SMatthew 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);
1698b5da9499SMatthew G. Knepley       }
1699b5da9499SMatthew G. Knepley #endif
1700b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0+4;
1701b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
1702b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1703b5da9499SMatthew G. Knepley #if 1
1704b5da9499SMatthew 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);
1705b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1706b5da9499SMatthew 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);
1707b5da9499SMatthew G. Knepley       }
1708b5da9499SMatthew G. Knepley #endif
1709b5da9499SMatthew G. Knepley       ++newp;
1710b5da9499SMatthew G. Knepley       /* Face F: {c, a, f} */
1711b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+0)%3 : (ornt[0]+2)%3);
1712b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1713b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1714b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1715b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+2)%3 : (ornt[2]+0)%3);
1716b5da9499SMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? 0 : -2;
1717b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1718b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1719b5da9499SMatthew G. Knepley #if 1
1720b5da9499SMatthew 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);
1721b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1722b5da9499SMatthew 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);
1723b5da9499SMatthew G. Knepley       }
1724b5da9499SMatthew G. Knepley #endif
1725b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0+4;
1726b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
1727b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1728b5da9499SMatthew G. Knepley #if 1
1729b5da9499SMatthew 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);
1730b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1731b5da9499SMatthew 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);
1732b5da9499SMatthew G. Knepley       }
1733b5da9499SMatthew G. Knepley #endif
1734b5da9499SMatthew G. Knepley       ++newp;
1735b5da9499SMatthew G. Knepley       /* Face G: {e, a, f} */
1736b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+1)%3 : (ornt[1]+1)%3);
1737b5da9499SMatthew G. Knepley       orntNew[0] = ornt[1] < 0 ? -2 : 0;
1738b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1739b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1740b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+1)%3 : (ornt[3]+1)%3);
1741b5da9499SMatthew G. Knepley       orntNew[2] = ornt[3] < 0 ? 0 : -2;
1742b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1743b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1744b5da9499SMatthew G. Knepley #if 1
1745b5da9499SMatthew 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);
1746b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1747b5da9499SMatthew 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);
1748b5da9499SMatthew G. Knepley       }
1749b5da9499SMatthew G. Knepley #endif
1750b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1+4;
1751b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
1752b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1753b5da9499SMatthew G. Knepley #if 1
1754b5da9499SMatthew 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);
1755b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1756b5da9499SMatthew 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);
1757b5da9499SMatthew G. Knepley       }
1758b5da9499SMatthew G. Knepley #endif
1759b5da9499SMatthew G. Knepley       ++newp;
1760b5da9499SMatthew G. Knepley       /* Face H: {a, b, f} */
1761b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+2)%3 : (ornt[0]+0)%3);
1762b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1763b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+0)%3 : (ornt[3]+2)%3);
1764b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? 0 : -2;
1765b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1766b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1767b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1768b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1769b5da9499SMatthew G. Knepley #if 1
1770b5da9499SMatthew 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);
1771b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1772b5da9499SMatthew 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);
1773b5da9499SMatthew G. Knepley       }
1774b5da9499SMatthew G. Knepley #endif
1775b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1+4;
1776b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
1777b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1778b5da9499SMatthew G. Knepley #if 1
1779b5da9499SMatthew 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);
1780b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1781b5da9499SMatthew 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);
1782b5da9499SMatthew G. Knepley       }
1783b5da9499SMatthew G. Knepley #endif
1784b5da9499SMatthew G. Knepley       ++newp;
1785b5da9499SMatthew G. Knepley     }
1786b5da9499SMatthew G. Knepley     /* Split Edges have 2 vertices and the same faces as the parent */
1787b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
1788b5da9499SMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
1789b5da9499SMatthew G. Knepley 
1790b5da9499SMatthew G. Knepley       for (r = 0; r < 2; ++r) {
1791b5da9499SMatthew G. Knepley         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
1792b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
1793b5da9499SMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
1794b5da9499SMatthew G. Knepley 
1795b5da9499SMatthew G. Knepley         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
1796b5da9499SMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
1797b5da9499SMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
1798b5da9499SMatthew G. Knepley         coneNew[(r+1)%2] = newv;
1799b5da9499SMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1800b5da9499SMatthew G. Knepley #if 1
1801b5da9499SMatthew 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);
1802b5da9499SMatthew G. Knepley         for (p = 0; p < 2; ++p) {
1803b5da9499SMatthew 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);
1804b5da9499SMatthew G. Knepley         }
1805b5da9499SMatthew G. Knepley #endif
1806b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
1807b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
1808b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
1809b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1810b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1811b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1812b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
1813b5da9499SMatthew G. Knepley             if (cone[c] == e) break;
1814b5da9499SMatthew G. Knepley           }
1815b5da9499SMatthew G. Knepley           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
1816b5da9499SMatthew G. Knepley         }
1817b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1818b5da9499SMatthew G. Knepley #if 1
1819b5da9499SMatthew 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);
1820b5da9499SMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
1821b5da9499SMatthew 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);
1822b5da9499SMatthew G. Knepley         }
1823b5da9499SMatthew G. Knepley #endif
1824b5da9499SMatthew G. Knepley       }
1825b5da9499SMatthew G. Knepley     }
182686f0afeeSMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
1827b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
1828b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt, *support;
1829b5da9499SMatthew G. Knepley       PetscInt        coneSize, supportSize, s;
1830b5da9499SMatthew G. Knepley 
1831b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1832b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1833b5da9499SMatthew G. Knepley       for (r = 0; r < 3; ++r) {
1834b5da9499SMatthew G. Knepley         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
1835b5da9499SMatthew G. Knepley         PetscInt        coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
1836b5da9499SMatthew G. Knepley         PetscInt        fint[24] = { 1,  7, -1, -1,  0,  5,
1837b5da9499SMatthew G. Knepley                                     -1, -1,  1,  6,  0,  4,
1838b5da9499SMatthew G. Knepley                                      2,  5,  3,  4, -1, -1,
1839b5da9499SMatthew G. Knepley                                     -1, -1,  3,  6,  2,  7};
1840b5da9499SMatthew G. Knepley 
1841b5da9499SMatthew G. Knepley         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1842b5da9499SMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
1843b5da9499SMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
1844b5da9499SMatthew G. Knepley         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1845b5da9499SMatthew G. Knepley #if 1
1846b5da9499SMatthew 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);
1847b5da9499SMatthew G. Knepley         for (p = 0; p < 2; ++p) {
1848b5da9499SMatthew 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);
1849b5da9499SMatthew G. Knepley         }
1850b5da9499SMatthew G. Knepley #endif
1851b5da9499SMatthew G. Knepley         supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
1852b5da9499SMatthew G. Knepley         supportRef[1] = fStartNew + (f - fStart)*4 + 3;
1853b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
1854b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1855b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1856b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1857b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
185886f0afeeSMatthew G. Knepley           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
185986f0afeeSMatthew G. Knepley           er   = ornt[c] < 0 ? (-(ornt[c]+1) + 2-r)%3 : (ornt[c] + r)%3;
1860b5da9499SMatthew G. Knepley           if (er == eint[c]) {
1861b5da9499SMatthew G. Knepley             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
1862b5da9499SMatthew G. Knepley           } else {
1863b5da9499SMatthew G. Knepley             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
1864b5da9499SMatthew G. Knepley             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
1865b5da9499SMatthew G. Knepley           }
1866b5da9499SMatthew G. Knepley         }
1867b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1868b5da9499SMatthew G. Knepley #if 1
1869b5da9499SMatthew 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);
1870b5da9499SMatthew G. Knepley         for (p = 0; p < intFaces; ++p) {
1871b5da9499SMatthew 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);
1872b5da9499SMatthew G. Knepley         }
1873b5da9499SMatthew G. Knepley #endif
1874b5da9499SMatthew G. Knepley       }
1875b5da9499SMatthew G. Knepley     }
1876b5da9499SMatthew G. Knepley     /* Interior edges have 2 vertices and 4 faces */
1877b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1878b5da9499SMatthew G. Knepley       const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1879b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt, *fcone;
18804a40f731SMatthew G. Knepley       PetscInt        coneNew[2], supportNew[4], find;
1881b5da9499SMatthew G. Knepley 
1882b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1883b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1884b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, cone[0], &fcone);CHKERRQ(ierr);
188542525629SMatthew G. Knepley       find = GetTriEdge_Static(ornt[0], 0);
1886b5da9499SMatthew G. Knepley       coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
1887b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, cone[2], &fcone);CHKERRQ(ierr);
188842525629SMatthew G. Knepley       find = GetTriEdge_Static(ornt[2], 1);
1889b5da9499SMatthew G. Knepley       coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
1890b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1891b5da9499SMatthew G. Knepley #if 1
1892b5da9499SMatthew 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);
1893b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1894b5da9499SMatthew 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);
1895b5da9499SMatthew G. Knepley       }
1896b5da9499SMatthew G. Knepley #endif
1897b5da9499SMatthew G. Knepley       supportNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
1898b5da9499SMatthew G. Knepley       supportNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
1899b5da9499SMatthew G. Knepley       supportNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
1900b5da9499SMatthew G. Knepley       supportNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
1901b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1902b5da9499SMatthew G. Knepley #if 1
1903b5da9499SMatthew 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);
1904b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1905b5da9499SMatthew 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);
1906b5da9499SMatthew G. Knepley       }
1907b5da9499SMatthew G. Knepley #endif
1908b5da9499SMatthew G. Knepley     }
1909b5da9499SMatthew G. Knepley     /* Old vertices have identical supports */
1910b5da9499SMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
1911b5da9499SMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
1912b5da9499SMatthew G. Knepley       const PetscInt *support, *cone;
1913b5da9499SMatthew G. Knepley       PetscInt        size, s;
1914b5da9499SMatthew G. Knepley 
1915b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
1916b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
1917b5da9499SMatthew G. Knepley       for (s = 0; s < size; ++s) {
1918b5da9499SMatthew G. Knepley         PetscInt r = 0;
1919b5da9499SMatthew G. Knepley 
1920b5da9499SMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1921b5da9499SMatthew G. Knepley         if (cone[1] == v) r = 1;
1922b5da9499SMatthew G. Knepley         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
1923b5da9499SMatthew G. Knepley       }
1924b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1925b5da9499SMatthew G. Knepley #if 1
1926b5da9499SMatthew 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);
1927b5da9499SMatthew G. Knepley       for (p = 0; p < size; ++p) {
1928b5da9499SMatthew 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);
1929b5da9499SMatthew G. Knepley       }
1930b5da9499SMatthew G. Knepley #endif
1931b5da9499SMatthew G. Knepley     }
1932b5da9499SMatthew G. Knepley     /* Edge vertices have 2 + face*2 + 0/1 supports */
1933b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
1934b5da9499SMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
1935b5da9499SMatthew G. Knepley       const PetscInt *cone, *support;
1936b5da9499SMatthew G. Knepley       PetscInt       *star = NULL, starSize, cellSize = 0, coneSize, size, s;
1937b5da9499SMatthew G. Knepley 
1938b5da9499SMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1939b5da9499SMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
1940b5da9499SMatthew G. Knepley       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
1941b5da9499SMatthew G. Knepley       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
1942b5da9499SMatthew G. Knepley       for (s = 0; s < size; ++s) {
1943b5da9499SMatthew G. Knepley         PetscInt r = 0;
1944b5da9499SMatthew G. Knepley 
1945b5da9499SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1946b5da9499SMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1947b5da9499SMatthew G. Knepley         for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
1948b5da9499SMatthew G. Knepley         supportRef[2+s*2+0] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
1949b5da9499SMatthew G. Knepley         supportRef[2+s*2+1] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
1950b5da9499SMatthew G. Knepley       }
1951b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
1952b5da9499SMatthew G. Knepley       for (s = 0; s < starSize*2; s += 2) {
1953b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt;
1954b5da9499SMatthew G. Knepley         PetscInt        e01, e23;
1955b5da9499SMatthew G. Knepley 
1956b5da9499SMatthew G. Knepley         if ((star[s] >= cStart) && (star[s] < cEnd)) {
1957b5da9499SMatthew G. Knepley           /* Check edge 0-1 */
1958b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
1959b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
1960b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
196142525629SMatthew G. Knepley           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
1962b5da9499SMatthew G. Knepley           /* Check edge 2-3 */
1963b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
1964b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
196542525629SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
196642525629SMatthew G. Knepley           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
1967b5da9499SMatthew G. Knepley           if ((e01 == e) || (e23 == e)) {supportRef[2+size*2+cellSize++] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (star[s] - cStart);}
1968b5da9499SMatthew G. Knepley         }
1969b5da9499SMatthew G. Knepley       }
1970b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
1971b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1972b5da9499SMatthew G. Knepley #if 1
1973b5da9499SMatthew 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);
1974b5da9499SMatthew G. Knepley       for (p = 0; p < 2+size*2+cellSize; ++p) {
1975b5da9499SMatthew 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);
1976b5da9499SMatthew G. Knepley       }
1977b5da9499SMatthew G. Knepley #endif
1978b5da9499SMatthew G. Knepley     }
1979b5da9499SMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
1980b5da9499SMatthew G. Knepley     ierr = DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);CHKERRQ(ierr);
1981b5da9499SMatthew G. Knepley     break;
19822eabf88fSMatthew G. Knepley   case 6:
19832eabf88fSMatthew G. Knepley     /* Hex 3D */
19842eabf88fSMatthew G. Knepley     /*
19852eabf88fSMatthew G. Knepley      Bottom (viewed from top)    Top
19862eabf88fSMatthew G. Knepley      1---------2---------2       7---------2---------6
19872eabf88fSMatthew G. Knepley      |         |         |       |         |         |
19882eabf88fSMatthew G. Knepley      |    B    2    C    |       |    H    2    G    |
19892eabf88fSMatthew G. Knepley      |         |         |       |         |         |
19902eabf88fSMatthew G. Knepley      3----3----0----1----1       3----3----0----1----1
19912eabf88fSMatthew G. Knepley      |         |         |       |         |         |
19922eabf88fSMatthew G. Knepley      |    A    0    D    |       |    E    0    F    |
19932eabf88fSMatthew G. Knepley      |         |         |       |         |         |
19942eabf88fSMatthew G. Knepley      0---------0---------3       4---------0---------5
19952eabf88fSMatthew G. Knepley      */
19962eabf88fSMatthew G. Knepley     /* All cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
19972eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
19982eabf88fSMatthew G. Knepley       const PetscInt  newp = (c - cStart)*8;
19992eabf88fSMatthew G. Knepley       const PetscInt *cone, *ornt;
20002eabf88fSMatthew G. Knepley       PetscInt        coneNew[6], orntNew[6];
20012eabf88fSMatthew G. Knepley 
20022eabf88fSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
20032eabf88fSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
20042eabf88fSMatthew G. Knepley       /* A hex */
2005e3f8b1d6SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
20062eabf88fSMatthew G. Knepley       orntNew[0] = ornt[0];
20072eabf88fSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
20082eabf88fSMatthew G. Knepley       orntNew[1] = 0;
2009e3f8b1d6SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
20102eabf88fSMatthew G. Knepley       orntNew[2] = ornt[2];
20112eabf88fSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
20122eabf88fSMatthew G. Knepley       orntNew[3] = 0;
20132eabf88fSMatthew G. Knepley       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
20142eabf88fSMatthew G. Knepley       orntNew[4] = 0;
2015e3f8b1d6SMatthew G. Knepley       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
20162eabf88fSMatthew G. Knepley       orntNew[5] = ornt[5];
20172eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
20182eabf88fSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
20192eabf88fSMatthew G. Knepley #if 1
20202eabf88fSMatthew 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);
20212eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
20222eabf88fSMatthew 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);
20232eabf88fSMatthew G. Knepley       }
20242eabf88fSMatthew G. Knepley #endif
20252eabf88fSMatthew G. Knepley       /* B hex */
2026e3f8b1d6SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
20272eabf88fSMatthew G. Knepley       orntNew[0] = ornt[0];
20282eabf88fSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
20292eabf88fSMatthew G. Knepley       orntNew[1] = 0;
20302eabf88fSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
20312eabf88fSMatthew G. Knepley       orntNew[2] = -3;
2032e3f8b1d6SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
20332eabf88fSMatthew G. Knepley       orntNew[3] = ornt[3];
20342eabf88fSMatthew G. Knepley       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
20352eabf88fSMatthew G. Knepley       orntNew[4] = 0;
2036e3f8b1d6SMatthew G. Knepley       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
20372eabf88fSMatthew G. Knepley       orntNew[5] = ornt[5];
20382eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
20392eabf88fSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
20402eabf88fSMatthew G. Knepley #if 1
20412eabf88fSMatthew 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);
20422eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
20432eabf88fSMatthew 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);
20442eabf88fSMatthew G. Knepley       }
20452eabf88fSMatthew G. Knepley #endif
20462eabf88fSMatthew G. Knepley       /* C hex */
2047e3f8b1d6SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
20482eabf88fSMatthew G. Knepley       orntNew[0] = ornt[0];
20492eabf88fSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
20502eabf88fSMatthew G. Knepley       orntNew[1] = 0;
20512eabf88fSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
20522eabf88fSMatthew G. Knepley       orntNew[2] = 0;
2053e3f8b1d6SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
20542eabf88fSMatthew G. Knepley       orntNew[3] = ornt[3];
2055e3f8b1d6SMatthew G. Knepley       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
20562eabf88fSMatthew G. Knepley       orntNew[4] = ornt[4];
20572eabf88fSMatthew G. Knepley       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
20582eabf88fSMatthew G. Knepley       orntNew[5] = -3;
20592eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
20602eabf88fSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
20612eabf88fSMatthew G. Knepley #if 1
20622eabf88fSMatthew 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);
20632eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
20642eabf88fSMatthew 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);
20652eabf88fSMatthew G. Knepley       }
20662eabf88fSMatthew G. Knepley #endif
20672eabf88fSMatthew G. Knepley       /* D hex */
2068e3f8b1d6SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
20692eabf88fSMatthew G. Knepley       orntNew[0] = ornt[0];
20702eabf88fSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
20712eabf88fSMatthew G. Knepley       orntNew[1] = 0;
2072e3f8b1d6SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
20732eabf88fSMatthew G. Knepley       orntNew[2] = ornt[2];
20742eabf88fSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
20752eabf88fSMatthew G. Knepley       orntNew[3] = -3;
2076e3f8b1d6SMatthew G. Knepley       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
20772eabf88fSMatthew G. Knepley       orntNew[4] = ornt[4];
20782eabf88fSMatthew G. Knepley       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
20792eabf88fSMatthew G. Knepley       orntNew[5] = -3;
20802eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
20812eabf88fSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
20822eabf88fSMatthew G. Knepley #if 1
20832eabf88fSMatthew 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);
20842eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
20852eabf88fSMatthew 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);
20862eabf88fSMatthew G. Knepley       }
20872eabf88fSMatthew G. Knepley #endif
20882eabf88fSMatthew G. Knepley       /* E hex */
20892eabf88fSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
20902eabf88fSMatthew G. Knepley       orntNew[0] = -3;
2091e3f8b1d6SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
20922eabf88fSMatthew G. Knepley       orntNew[1] = ornt[1];
2093e3f8b1d6SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
20942eabf88fSMatthew G. Knepley       orntNew[2] = ornt[2];
20952eabf88fSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
20962eabf88fSMatthew G. Knepley       orntNew[3] = 0;
20972eabf88fSMatthew G. Knepley       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
20982eabf88fSMatthew G. Knepley       orntNew[4] = 0;
2099e3f8b1d6SMatthew G. Knepley       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
21002eabf88fSMatthew G. Knepley       orntNew[5] = ornt[5];
2101b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
2102b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
21032eabf88fSMatthew G. Knepley #if 1
2104b164cbf2SMatthew 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);
21052eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
21062eabf88fSMatthew 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);
21072eabf88fSMatthew G. Knepley       }
21082eabf88fSMatthew G. Knepley #endif
21092eabf88fSMatthew G. Knepley       /* F hex */
21102eabf88fSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
21112eabf88fSMatthew G. Knepley       orntNew[0] = -3;
2112e3f8b1d6SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
21132eabf88fSMatthew G. Knepley       orntNew[1] = ornt[1];
2114e3f8b1d6SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
21152eabf88fSMatthew G. Knepley       orntNew[2] = ornt[2];
21162eabf88fSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
21172eabf88fSMatthew G. Knepley       orntNew[3] = 0;
2118e3f8b1d6SMatthew G. Knepley       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
21192eabf88fSMatthew G. Knepley       orntNew[4] = ornt[4];
21202eabf88fSMatthew G. Knepley       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
21212eabf88fSMatthew G. Knepley       orntNew[5] = -3;
2122b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
2123b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
21242eabf88fSMatthew G. Knepley #if 1
2125b164cbf2SMatthew 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);
21262eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
21272eabf88fSMatthew 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);
21282eabf88fSMatthew G. Knepley       }
21292eabf88fSMatthew G. Knepley #endif
21302eabf88fSMatthew G. Knepley       /* G hex */
21312eabf88fSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
21322eabf88fSMatthew G. Knepley       orntNew[0] = -3;
2133e3f8b1d6SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
21342eabf88fSMatthew G. Knepley       orntNew[1] = ornt[1];
21352eabf88fSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
21362eabf88fSMatthew G. Knepley       orntNew[2] = -3;
2137e3f8b1d6SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
21382eabf88fSMatthew G. Knepley       orntNew[3] = ornt[3];
2139e3f8b1d6SMatthew G. Knepley       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
21402eabf88fSMatthew G. Knepley       orntNew[4] = ornt[4];
21412eabf88fSMatthew G. Knepley       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
21422eabf88fSMatthew G. Knepley       orntNew[5] = 0;
2143b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
2144b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
21452eabf88fSMatthew G. Knepley #if 1
2146b164cbf2SMatthew 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);
21472eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
21482eabf88fSMatthew 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);
21492eabf88fSMatthew G. Knepley       }
21502eabf88fSMatthew G. Knepley #endif
21512eabf88fSMatthew G. Knepley       /* H hex */
21522eabf88fSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
21532eabf88fSMatthew G. Knepley       orntNew[0] = -3;
2154e3f8b1d6SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
21552eabf88fSMatthew G. Knepley       orntNew[1] = ornt[1];
21562eabf88fSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
21572eabf88fSMatthew G. Knepley       orntNew[2] = -3;
2158e3f8b1d6SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
21592eabf88fSMatthew G. Knepley       orntNew[3] = ornt[3];
21602eabf88fSMatthew G. Knepley       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
21612eabf88fSMatthew G. Knepley       orntNew[4] = -3;
2162e3f8b1d6SMatthew G. Knepley       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
21632eabf88fSMatthew G. Knepley       orntNew[5] = ornt[5];
2164b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
2165b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
21662eabf88fSMatthew G. Knepley #if 1
2167b164cbf2SMatthew 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);
21682eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
21692eabf88fSMatthew 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);
21702eabf88fSMatthew G. Knepley       }
21712eabf88fSMatthew G. Knepley #endif
21722eabf88fSMatthew G. Knepley     }
21732eabf88fSMatthew G. Knepley     /* Split faces have 4 edges and the same cells as the parent */
21742eabf88fSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
21752eabf88fSMatthew G. Knepley     ierr = PetscMalloc((4 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
21762eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
21772eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
2178*aaebbb9dSMatthew G. Knepley         /* TODO: This can come from GetFaces_Internal() */
21792eabf88fSMatthew 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};
21802eabf88fSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*4 + r;
21812eabf88fSMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
2182*aaebbb9dSMatthew G. Knepley         PetscInt        coneNew[4], orntNew[4], coneSize, c, supportSize, s;
21832eabf88fSMatthew G. Knepley 
21842eabf88fSMatthew G. Knepley         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
2185*aaebbb9dSMatthew G. Knepley         ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
2186*aaebbb9dSMatthew G. Knepley         coneNew[0] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
2187*aaebbb9dSMatthew G. Knepley         orntNew[0] = ornt[(r+3)%4];
2188*aaebbb9dSMatthew G. Knepley         coneNew[1] = eStartNew + (cone[r]       - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
2189*aaebbb9dSMatthew G. Knepley         orntNew[1] = ornt[r];
21902eabf88fSMatthew G. Knepley         coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
2191*aaebbb9dSMatthew G. Knepley         orntNew[2] = 0;
21922eabf88fSMatthew G. Knepley         coneNew[3] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + (r+3)%4;
2193*aaebbb9dSMatthew G. Knepley         orntNew[3] = -2;
21942eabf88fSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2195*aaebbb9dSMatthew G. Knepley         ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
21962eabf88fSMatthew G. Knepley #if 1
21972eabf88fSMatthew 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);
21982eabf88fSMatthew G. Knepley         for (p = 0; p < 4; ++p) {
21992eabf88fSMatthew 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);
22002eabf88fSMatthew G. Knepley         }
22012eabf88fSMatthew G. Knepley #endif
22022eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
22032eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
22042eabf88fSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
22052eabf88fSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
22062eabf88fSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
22072eabf88fSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
22082eabf88fSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
22092eabf88fSMatthew G. Knepley             if (cone[c] == f) break;
22102eabf88fSMatthew G. Knepley           }
22112eabf88fSMatthew G. Knepley           /* TODO: Redo using orientation information */
22122eabf88fSMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+r];
22132eabf88fSMatthew G. Knepley         }
22142eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
22152eabf88fSMatthew G. Knepley #if 1
22162eabf88fSMatthew 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);
22172eabf88fSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
22182eabf88fSMatthew 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);
22192eabf88fSMatthew G. Knepley         }
22202eabf88fSMatthew G. Knepley #endif
22212eabf88fSMatthew G. Knepley       }
22222eabf88fSMatthew G. Knepley     }
22232eabf88fSMatthew G. Knepley     /* Interior faces have 4 edges and 2 cells */
22242eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
22252eabf88fSMatthew 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};
22262eabf88fSMatthew G. Knepley       const PetscInt *cone;
22272eabf88fSMatthew G. Knepley       PetscInt        coneNew[4], supportNew[2];
22282eabf88fSMatthew G. Knepley 
22292eabf88fSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
22302eabf88fSMatthew G. Knepley       for (r = 0; r < 12; ++r) {
22312eabf88fSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
22322eabf88fSMatthew G. Knepley 
22332eabf88fSMatthew G. Knepley         coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[r] - fStart);
22342eabf88fSMatthew G. Knepley         coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart) + (c - cStart);
22352eabf88fSMatthew G. Knepley         coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[r] - fStart);
22362eabf88fSMatthew G. Knepley         coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[r] - fStart);
22372eabf88fSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
22382eabf88fSMatthew G. Knepley #if 1
22392eabf88fSMatthew 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);
22402eabf88fSMatthew G. Knepley         for (p = 0; p < 4; ++p) {
22412eabf88fSMatthew 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);
22422eabf88fSMatthew G. Knepley         }
22432eabf88fSMatthew G. Knepley #endif
22442eabf88fSMatthew G. Knepley         supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
22452eabf88fSMatthew G. Knepley         supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
22462eabf88fSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
22472eabf88fSMatthew G. Knepley #if 1
22482eabf88fSMatthew 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);
22492eabf88fSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
22502eabf88fSMatthew 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);
22512eabf88fSMatthew G. Knepley         }
22522eabf88fSMatthew G. Knepley #endif
22532eabf88fSMatthew G. Knepley       }
22542eabf88fSMatthew G. Knepley     }
22552eabf88fSMatthew G. Knepley     /* Split edges have 2 vertices and the same faces as the parent */
22562eabf88fSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
22572eabf88fSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
22582eabf88fSMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
22592eabf88fSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
22602eabf88fSMatthew G. Knepley 
22612eabf88fSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
22622eabf88fSMatthew G. Knepley         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
22632eabf88fSMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
22642eabf88fSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
22652eabf88fSMatthew G. Knepley 
22662eabf88fSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
22672eabf88fSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
22682eabf88fSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
22692eabf88fSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
22702eabf88fSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
22712eabf88fSMatthew G. Knepley #if 1
22722eabf88fSMatthew 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);
22732eabf88fSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
22742eabf88fSMatthew 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);
22752eabf88fSMatthew G. Knepley         }
22762eabf88fSMatthew G. Knepley #endif
22772eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
22782eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
22792eabf88fSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
22802eabf88fSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
22812eabf88fSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
22822eabf88fSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
22832eabf88fSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
22842eabf88fSMatthew G. Knepley             if (cone[c] == e) break;
22852eabf88fSMatthew G. Knepley           }
22862eabf88fSMatthew G. Knepley           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
22872eabf88fSMatthew G. Knepley         }
22882eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
22892eabf88fSMatthew G. Knepley #if 1
22902eabf88fSMatthew 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);
22912eabf88fSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
22922eabf88fSMatthew 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);
22932eabf88fSMatthew G. Knepley         }
22942eabf88fSMatthew G. Knepley #endif
22952eabf88fSMatthew G. Knepley       }
22962eabf88fSMatthew G. Knepley     }
22972eabf88fSMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells faces */
22982eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
22992eabf88fSMatthew 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};
23002eabf88fSMatthew G. Knepley       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
23012eabf88fSMatthew G. Knepley       const PetscInt *cone, *coneCell, *support;
23022eabf88fSMatthew G. Knepley       PetscInt        coneNew[2], coneSize, c, supportSize, s;
23032eabf88fSMatthew G. Knepley 
23042eabf88fSMatthew G. Knepley       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
23052eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
23062eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
23072eabf88fSMatthew G. Knepley 
23082eabf88fSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
23092eabf88fSMatthew G. Knepley         coneNew[1] = newv;
23102eabf88fSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
23112eabf88fSMatthew G. Knepley #if 1
23122eabf88fSMatthew 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);
23132eabf88fSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
23142eabf88fSMatthew 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);
23152eabf88fSMatthew G. Knepley         }
23162eabf88fSMatthew G. Knepley #endif
23172eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
23182eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
23192eabf88fSMatthew G. Knepley         supportRef[0] = fStartNew + (f - fStart)*4 + r;
23202eabf88fSMatthew G. Knepley         supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
23212eabf88fSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
2322e19c037eSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr);
23232eabf88fSMatthew G. Knepley           ierr = DMPlexGetCone(dm, f, &coneCell);CHKERRQ(ierr);
23242eabf88fSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
23252eabf88fSMatthew G. Knepley           supportRef[2+s] = fStartNew + (f - fStart)*4 + newFaces[c*4+r];
23262eabf88fSMatthew G. Knepley         }
23272eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
23282eabf88fSMatthew G. Knepley #if 1
23292eabf88fSMatthew 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);
23302eabf88fSMatthew G. Knepley         for (p = 0; p < 2+supportSize; ++p) {
23312eabf88fSMatthew 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);
23322eabf88fSMatthew G. Knepley         }
23332eabf88fSMatthew G. Knepley #endif
23342eabf88fSMatthew G. Knepley       }
23352eabf88fSMatthew G. Knepley     }
23362eabf88fSMatthew G. Knepley     /* Cell edges have 2 vertices and 4 faces */
23372eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
23382eabf88fSMatthew 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};
23392eabf88fSMatthew G. Knepley       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
23402eabf88fSMatthew G. Knepley       const PetscInt *cone;
23412eabf88fSMatthew G. Knepley       PetscInt        coneNew[2], supportNew[4];
23422eabf88fSMatthew G. Knepley 
23432eabf88fSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
23442eabf88fSMatthew G. Knepley       for (r = 0; r < 6; ++r) {
23452eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
23462eabf88fSMatthew G. Knepley 
23472eabf88fSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
23482eabf88fSMatthew G. Knepley         coneNew[1] = newv;
23492eabf88fSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
23502eabf88fSMatthew G. Knepley #if 1
23512eabf88fSMatthew 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);
23522eabf88fSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
23532eabf88fSMatthew 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);
23542eabf88fSMatthew G. Knepley         }
23552eabf88fSMatthew G. Knepley #endif
23562eabf88fSMatthew G. Knepley         for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
23572eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
23582eabf88fSMatthew G. Knepley #if 1
23592eabf88fSMatthew 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);
23602eabf88fSMatthew G. Knepley         for (p = 0; p < 4; ++p) {
23612eabf88fSMatthew 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);
23622eabf88fSMatthew G. Knepley         }
23632eabf88fSMatthew G. Knepley #endif
23642eabf88fSMatthew G. Knepley       }
23652eabf88fSMatthew G. Knepley     }
23662eabf88fSMatthew G. Knepley     /* Old vertices have identical supports */
23672eabf88fSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
23682eabf88fSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
23692eabf88fSMatthew G. Knepley       const PetscInt *support, *cone;
23702eabf88fSMatthew G. Knepley       PetscInt        size, s;
23712eabf88fSMatthew G. Knepley 
23722eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
23732eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
23742eabf88fSMatthew G. Knepley       for (s = 0; s < size; ++s) {
23752eabf88fSMatthew G. Knepley         PetscInt r = 0;
23762eabf88fSMatthew G. Knepley 
23772eabf88fSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
23782eabf88fSMatthew G. Knepley         if (cone[1] == v) r = 1;
23792eabf88fSMatthew G. Knepley         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
23802eabf88fSMatthew G. Knepley       }
23812eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
23822eabf88fSMatthew G. Knepley #if 1
23832eabf88fSMatthew 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);
23842eabf88fSMatthew G. Knepley       for (p = 0; p < size; ++p) {
23852eabf88fSMatthew 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);
23862eabf88fSMatthew G. Knepley       }
23872eabf88fSMatthew G. Knepley #endif
23882eabf88fSMatthew G. Knepley     }
23892eabf88fSMatthew G. Knepley     /* Edge vertices have 2 + faces supports */
23902eabf88fSMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
23912eabf88fSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
23922eabf88fSMatthew G. Knepley       const PetscInt *cone, *support;
23932eabf88fSMatthew G. Knepley       PetscInt        size, s;
23942eabf88fSMatthew G. Knepley 
23952eabf88fSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
23962eabf88fSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
23972eabf88fSMatthew G. Knepley       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
23982eabf88fSMatthew G. Knepley       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
23992eabf88fSMatthew G. Knepley       for (s = 0; s < size; ++s) {
24002eabf88fSMatthew G. Knepley         PetscInt r;
24012eabf88fSMatthew G. Knepley 
24022eabf88fSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2403a660e16cSMatthew G. Knepley         for (r = 0; r < 4; ++r) if (cone[r] == e) break;
24042eabf88fSMatthew G. Knepley         supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*4 + r;
24052eabf88fSMatthew G. Knepley       }
24062eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
24072eabf88fSMatthew G. Knepley #if 1
24082eabf88fSMatthew 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);
24092eabf88fSMatthew G. Knepley       for (p = 0; p < 2+size; ++p) {
24102eabf88fSMatthew 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);
24112eabf88fSMatthew G. Knepley       }
24122eabf88fSMatthew G. Knepley #endif
24132eabf88fSMatthew G. Knepley     }
24142eabf88fSMatthew G. Knepley     /* Face vertices have 4 + cells supports */
24152eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
24162eabf88fSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
24172eabf88fSMatthew G. Knepley       const PetscInt *cone, *support;
24182eabf88fSMatthew G. Knepley       PetscInt        size, s;
24192eabf88fSMatthew G. Knepley 
24202eabf88fSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
24212eabf88fSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
24222eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (e - eStart)*2 +  (f - fStart)*4 + r;
24232eabf88fSMatthew G. Knepley       for (s = 0; s < size; ++s) {
24242eabf88fSMatthew G. Knepley         PetscInt r;
24252eabf88fSMatthew G. Knepley 
24262eabf88fSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
24272eabf88fSMatthew G. Knepley         for (r = 0; r < 6; ++r) if (cone[r] == f) break;
24282eabf88fSMatthew G. Knepley         supportRef[4+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (support[s] - cStart)*6 + r;
24292eabf88fSMatthew G. Knepley       }
24302eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
24312eabf88fSMatthew G. Knepley #if 1
24322eabf88fSMatthew 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);
24332eabf88fSMatthew G. Knepley       for (p = 0; p < 4+size; ++p) {
24342eabf88fSMatthew 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);
24352eabf88fSMatthew G. Knepley       }
24362eabf88fSMatthew G. Knepley #endif
24372eabf88fSMatthew G. Knepley     }
24382eabf88fSMatthew G. Knepley     /* Cell vertices have 6 supports */
24392eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
24402eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
24412eabf88fSMatthew G. Knepley       PetscInt       supportNew[6];
24422eabf88fSMatthew G. Knepley 
24432eabf88fSMatthew G. Knepley       for (r = 0; r < 6; ++r) {
24442eabf88fSMatthew G. Knepley         supportNew[r] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
24452eabf88fSMatthew G. Knepley       }
24462eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
24472eabf88fSMatthew G. Knepley     }
2448da00770fSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
24492eabf88fSMatthew G. Knepley     break;
245075d3a19aSMatthew G. Knepley   default:
245175d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
245275d3a19aSMatthew G. Knepley   }
245375d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
245475d3a19aSMatthew G. Knepley }
245575d3a19aSMatthew G. Knepley 
245675d3a19aSMatthew G. Knepley #undef __FUNCT__
245775d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetCoordinates"
245875d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
245975d3a19aSMatthew G. Knepley {
246075d3a19aSMatthew G. Knepley   PetscSection   coordSection, coordSectionNew;
246175d3a19aSMatthew G. Knepley   Vec            coordinates, coordinatesNew;
246275d3a19aSMatthew G. Knepley   PetscScalar   *coords, *coordsNew;
2463b5da9499SMatthew G. Knepley   PetscInt       dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, eStart, eEnd, eMax, e, fStart, fEnd, fMax, f;
246475d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
246575d3a19aSMatthew G. Knepley 
246675d3a19aSMatthew G. Knepley   PetscFunctionBegin;
246775d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
246875d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
246975d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
2470b5da9499SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
247175d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
247275d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
2473b5da9499SMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, &eMax, NULL);CHKERRQ(ierr);
247475d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr);
247575d3a19aSMatthew G. Knepley   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
247675d3a19aSMatthew G. Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr);
247775d3a19aSMatthew G. Knepley   ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr);
247875d3a19aSMatthew G. Knepley   ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr);
247975d3a19aSMatthew G. Knepley   ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr);
248075d3a19aSMatthew G. Knepley   if (fMax < 0) fMax = fEnd;
2481b5da9499SMatthew G. Knepley   if (eMax < 0) eMax = eEnd;
248275d3a19aSMatthew G. Knepley   /* All vertices have the dim coordinates */
248375d3a19aSMatthew G. Knepley   for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) {
248475d3a19aSMatthew G. Knepley     ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr);
248575d3a19aSMatthew G. Knepley     ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr);
248675d3a19aSMatthew G. Knepley   }
248775d3a19aSMatthew G. Knepley   ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr);
248875d3a19aSMatthew G. Knepley   ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr);
248975d3a19aSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
249075d3a19aSMatthew G. Knepley   ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr);
249175d3a19aSMatthew G. Knepley   ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr);
249275d3a19aSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr);
249375d3a19aSMatthew G. Knepley   ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr);
249475d3a19aSMatthew G. Knepley   ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr);
249575d3a19aSMatthew G. Knepley   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
249675d3a19aSMatthew G. Knepley   ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
2497b5da9499SMatthew G. Knepley   switch (refiner) {
2498b5da9499SMatthew G. Knepley   case 6: /* Hex 3D */
2499b5da9499SMatthew G. Knepley     /* Face vertices have the average of corner coordinates */
2500b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
2501c91acedaSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
2502b5da9499SMatthew G. Knepley       PetscInt      *cone = NULL;
2503b5da9499SMatthew G. Knepley       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;
2504b5da9499SMatthew G. Knepley 
2505b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
2506b5da9499SMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
2507b5da9499SMatthew G. Knepley         const PetscInt point = cone[p];
2508b5da9499SMatthew G. Knepley         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
2509b5da9499SMatthew G. Knepley       }
2510b5da9499SMatthew G. Knepley       for (v = 0; v < coneSize; ++v) {
2511b5da9499SMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[v], &off[v]);CHKERRQ(ierr);
2512b5da9499SMatthew G. Knepley       }
2513b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
2514b5da9499SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
2515b5da9499SMatthew G. Knepley         coordsNew[offnew+d] = 0.0;
2516b5da9499SMatthew G. Knepley         for (v = 0; v < coneSize; ++v) coordsNew[offnew+d] += coords[off[v]+d];
2517b5da9499SMatthew G. Knepley         coordsNew[offnew+d] /= coneSize;
2518b5da9499SMatthew G. Knepley       }
2519b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
2520b5da9499SMatthew G. Knepley     }
2521b5da9499SMatthew G. Knepley   case 2: /* Hex 2D */
2522b5da9499SMatthew G. Knepley     /* Cell vertices have the average of corner coordinates */
2523b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
2524c91acedaSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (c - cStart) + (dim > 2 ? (fEnd - fStart) : 0);
2525b5da9499SMatthew G. Knepley       PetscInt      *cone = NULL;
2526b5da9499SMatthew G. Knepley       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;
2527b5da9499SMatthew G. Knepley 
2528b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
2529b5da9499SMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
2530b5da9499SMatthew G. Knepley         const PetscInt point = cone[p];
2531b5da9499SMatthew G. Knepley         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
2532b5da9499SMatthew G. Knepley       }
2533b5da9499SMatthew G. Knepley       for (v = 0; v < coneSize; ++v) {
2534b5da9499SMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[v], &off[v]);CHKERRQ(ierr);
2535b5da9499SMatthew G. Knepley       }
2536b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
2537b5da9499SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
2538b5da9499SMatthew G. Knepley         coordsNew[offnew+d] = 0.0;
2539b5da9499SMatthew G. Knepley         for (v = 0; v < coneSize; ++v) coordsNew[offnew+d] += coords[off[v]+d];
2540b5da9499SMatthew G. Knepley         coordsNew[offnew+d] /= coneSize;
2541b5da9499SMatthew G. Knepley       }
2542b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
2543b5da9499SMatthew G. Knepley     }
2544b5da9499SMatthew G. Knepley   case 1: /* Simplicial 2D */
2545b5da9499SMatthew G. Knepley   case 3: /* Hybrid Simplicial 2D */
2546b5da9499SMatthew G. Knepley   case 5: /* Simplicial 3D */
2547b5da9499SMatthew G. Knepley     /* Edge vertices have the average of endpoint coordinates */
2548b5da9499SMatthew G. Knepley     for (e = eStart; e < eMax; ++e) {
2549b5da9499SMatthew G. Knepley       const PetscInt  newv = vStartNew + (vEnd - vStart) + (e - eStart);
2550b5da9499SMatthew G. Knepley       const PetscInt *cone;
2551b5da9499SMatthew G. Knepley       PetscInt        coneSize, offA, offB, offnew, d;
2552b5da9499SMatthew G. Knepley 
2553b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr);
2554b5da9499SMatthew G. Knepley       if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize);
2555b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
2556b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
2557b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
2558b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
2559b5da9499SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
2560b5da9499SMatthew G. Knepley         coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]);
2561b5da9499SMatthew G. Knepley       }
2562b5da9499SMatthew G. Knepley     }
256375d3a19aSMatthew G. Knepley     /* Old vertices have the same coordinates */
256475d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
256575d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (v - vStart);
256675d3a19aSMatthew G. Knepley       PetscInt       off, offnew, d;
256775d3a19aSMatthew G. Knepley 
256875d3a19aSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
256975d3a19aSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
257075d3a19aSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
257175d3a19aSMatthew G. Knepley         coordsNew[offnew+d] = coords[off+d];
257275d3a19aSMatthew G. Knepley       }
257375d3a19aSMatthew G. Knepley     }
2574b5da9499SMatthew G. Knepley     break;
2575b5da9499SMatthew G. Knepley   default:
2576b5da9499SMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
257775d3a19aSMatthew G. Knepley   }
257875d3a19aSMatthew G. Knepley   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
257975d3a19aSMatthew G. Knepley   ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
258075d3a19aSMatthew G. Knepley   ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr);
258175d3a19aSMatthew G. Knepley   ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr);
258275d3a19aSMatthew G. Knepley   ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr);
258375d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
258475d3a19aSMatthew G. Knepley }
258575d3a19aSMatthew G. Knepley 
258675d3a19aSMatthew G. Knepley #undef __FUNCT__
258775d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexCreateProcessSF"
258875d3a19aSMatthew G. Knepley PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
258975d3a19aSMatthew G. Knepley {
259075d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, l;
259175d3a19aSMatthew G. Knepley   const PetscInt    *localPoints;
259275d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
259375d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
259475d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
259575d3a19aSMatthew G. Knepley   PetscInt          *ranks, *ranksNew;
259675d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
259775d3a19aSMatthew G. Knepley 
259875d3a19aSMatthew G. Knepley   PetscFunctionBegin;
259975d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
260075d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr);
260175d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
260275d3a19aSMatthew G. Knepley     ranks[l] = remotePoints[l].rank;
260375d3a19aSMatthew G. Knepley   }
260475d3a19aSMatthew G. Knepley   ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr);
260575d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt),    &ranksNew);CHKERRQ(ierr);
260675d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt),    &localPointsNew);CHKERRQ(ierr);
260775d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr);
260875d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
260975d3a19aSMatthew G. Knepley     ranksNew[l]              = ranks[l];
261075d3a19aSMatthew G. Knepley     localPointsNew[l]        = l;
261175d3a19aSMatthew G. Knepley     remotePointsNew[l].index = 0;
261275d3a19aSMatthew G. Knepley     remotePointsNew[l].rank  = ranksNew[l];
261375d3a19aSMatthew G. Knepley   }
261475d3a19aSMatthew G. Knepley   ierr = PetscFree(ranks);CHKERRQ(ierr);
261575d3a19aSMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);
261675d3a19aSMatthew G. Knepley   ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr);
261775d3a19aSMatthew G. Knepley   ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr);
261875d3a19aSMatthew G. Knepley   ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
261975d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
262075d3a19aSMatthew G. Knepley }
262175d3a19aSMatthew G. Knepley 
262275d3a19aSMatthew G. Knepley #undef __FUNCT__
262375d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerCreateSF"
262475d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
262575d3a19aSMatthew G. Knepley {
262675d3a19aSMatthew G. Knepley   PetscSF            sf, sfNew, sfProcess;
262775d3a19aSMatthew G. Knepley   IS                 processRanks;
262875d3a19aSMatthew G. Knepley   MPI_Datatype       depthType;
262975d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
263075d3a19aSMatthew G. Knepley   const PetscInt    *localPoints, *neighbors;
263175d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
263275d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
263375d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
263475d3a19aSMatthew G. Knepley   PetscInt          *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
263575d3a19aSMatthew 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;
263675d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
263775d3a19aSMatthew G. Knepley 
263875d3a19aSMatthew G. Knepley   PetscFunctionBegin;
263975d3a19aSMatthew G. Knepley   ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr);
264075d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
264175d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
264275d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
264375d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
264475d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
264575d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
264675d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
264775d3a19aSMatthew G. Knepley   switch (refiner) {
264875d3a19aSMatthew G. Knepley   case 3:
264975d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
265075d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
265175d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
265275d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
265375d3a19aSMatthew G. Knepley   }
265475d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
265575d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr);
265675d3a19aSMatthew G. Knepley   /* Caculate size of new SF */
265775d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
265875d3a19aSMatthew G. Knepley   if (numRoots < 0) PetscFunctionReturn(0);
265975d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
266075d3a19aSMatthew G. Knepley     const PetscInt p = localPoints[l];
266175d3a19aSMatthew G. Knepley 
266275d3a19aSMatthew G. Knepley     switch (refiner) {
266375d3a19aSMatthew G. Knepley     case 1:
266475d3a19aSMatthew G. Knepley       /* Simplicial 2D */
266575d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
266675d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
266775d3a19aSMatthew G. Knepley         ++numLeavesNew;
266875d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
266975d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
2670d963de37SMatthew G. Knepley         numLeavesNew += 2 + 1;
267175d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
267275d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
267375d3a19aSMatthew G. Knepley         numLeavesNew += 4 + 3;
267475d3a19aSMatthew G. Knepley       }
267575d3a19aSMatthew G. Knepley       break;
267675d3a19aSMatthew G. Knepley     case 2:
267775d3a19aSMatthew G. Knepley       /* Hex 2D */
267875d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
267975d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
268075d3a19aSMatthew G. Knepley         ++numLeavesNew;
268175d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
268275d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
2683d963de37SMatthew G. Knepley         numLeavesNew += 2 + 1;
268475d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
2685455d6cd4SMatthew G. Knepley         /* Old cells add new cells, interior faces, and vertex */
2686455d6cd4SMatthew G. Knepley         numLeavesNew += 4 + 4 + 1;
268775d3a19aSMatthew G. Knepley       }
268875d3a19aSMatthew G. Knepley       break;
2689b5da9499SMatthew G. Knepley     case 5:
2690b5da9499SMatthew G. Knepley       /* Simplicial 3D */
2691b5da9499SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
2692b5da9499SMatthew G. Knepley         /* Old vertices stay the same */
2693b5da9499SMatthew G. Knepley         ++numLeavesNew;
2694b5da9499SMatthew G. Knepley       } else if ((p >= eStart) && (p < eEnd)) {
2695b5da9499SMatthew G. Knepley         /* Old edges add new edges and vertex */
2696b5da9499SMatthew G. Knepley         numLeavesNew += 2 + 1;
2697b5da9499SMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
2698b5da9499SMatthew G. Knepley         /* Old faces add new faces and face edges */
2699b5da9499SMatthew G. Knepley         numLeavesNew += 4 + 3;
2700b5da9499SMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
2701b5da9499SMatthew G. Knepley         /* Old cells add new cells and interior faces and edges */
2702b5da9499SMatthew G. Knepley         numLeavesNew += 8 + 8 + 1;
2703b5da9499SMatthew G. Knepley       }
2704b5da9499SMatthew G. Knepley       break;
27052eabf88fSMatthew G. Knepley     case 6:
27062eabf88fSMatthew G. Knepley       /* Hex 3D */
27072eabf88fSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
27082eabf88fSMatthew G. Knepley         /* Old vertices stay the same */
27092eabf88fSMatthew G. Knepley         ++numLeavesNew;
27102eabf88fSMatthew G. Knepley       } else if ((p >= eStart) && (p < eEnd)) {
27112eabf88fSMatthew G. Knepley         /* Old edges add new edges, and vertex */
27122eabf88fSMatthew G. Knepley         numLeavesNew += 2 + 1;
27132eabf88fSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
27142eabf88fSMatthew G. Knepley         /* Old faces add new faces, edges, and vertex */
27152eabf88fSMatthew G. Knepley         numLeavesNew += 4 + 4 + 1;
27162eabf88fSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
27172eabf88fSMatthew G. Knepley         /* Old cells add new cells, faces, edges, and vertex */
27182eabf88fSMatthew G. Knepley         numLeavesNew += 8 + 12 + 6 + 1;
27192eabf88fSMatthew G. Knepley       }
27202eabf88fSMatthew G. Knepley       break;
272175d3a19aSMatthew G. Knepley     default:
272275d3a19aSMatthew G. Knepley       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
272375d3a19aSMatthew G. Knepley     }
272475d3a19aSMatthew G. Knepley   }
272575d3a19aSMatthew G. Knepley   /* Communicate depthSizes for each remote rank */
272675d3a19aSMatthew G. Knepley   ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr);
272775d3a19aSMatthew G. Knepley   ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr);
272875d3a19aSMatthew G. Knepley   ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr);
272975d3a19aSMatthew 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);
273075d3a19aSMatthew G. Knepley   ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr);
273175d3a19aSMatthew G. Knepley   ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr);
273275d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
273375d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
273475d3a19aSMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {
273575d3a19aSMatthew G. Knepley     ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr);
273675d3a19aSMatthew G. Knepley   }
273775d3a19aSMatthew G. Knepley   depthSizeOld[depth]   = cMax;
273875d3a19aSMatthew G. Knepley   depthSizeOld[0]       = vMax;
273975d3a19aSMatthew G. Knepley   depthSizeOld[depth-1] = fMax;
274075d3a19aSMatthew G. Knepley   depthSizeOld[1]       = eMax;
274175d3a19aSMatthew G. Knepley 
274275d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
274375d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
274475d3a19aSMatthew G. Knepley 
274575d3a19aSMatthew G. Knepley   depthSizeOld[depth]   = cEnd - cStart;
274675d3a19aSMatthew G. Knepley   depthSizeOld[0]       = vEnd - vStart;
274775d3a19aSMatthew G. Knepley   depthSizeOld[depth-1] = fEnd - fStart;
274875d3a19aSMatthew G. Knepley   depthSizeOld[1]       = eEnd - eStart;
274975d3a19aSMatthew G. Knepley 
275075d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
275175d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
275275d3a19aSMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {
275375d3a19aSMatthew G. Knepley     ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr);
275475d3a19aSMatthew G. Knepley   }
275575d3a19aSMatthew G. Knepley   ierr = MPI_Type_free(&depthType);CHKERRQ(ierr);
275675d3a19aSMatthew G. Knepley   ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr);
275775d3a19aSMatthew G. Knepley   /* Calculate new point SF */
275875d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt),    &localPointsNew);CHKERRQ(ierr);
275975d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr);
276075d3a19aSMatthew G. Knepley   ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr);
276175d3a19aSMatthew G. Knepley   for (l = 0, m = 0; l < numLeaves; ++l) {
276275d3a19aSMatthew G. Knepley     PetscInt    p     = localPoints[l];
276375d3a19aSMatthew G. Knepley     PetscInt    rp    = remotePoints[l].index, n;
276475d3a19aSMatthew G. Knepley     PetscMPIInt rrank = remotePoints[l].rank;
276575d3a19aSMatthew G. Knepley 
276675d3a19aSMatthew G. Knepley     ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr);
276775d3a19aSMatthew G. Knepley     if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank);
276875d3a19aSMatthew G. Knepley     switch (refiner) {
276975d3a19aSMatthew G. Knepley     case 1:
277075d3a19aSMatthew G. Knepley       /* Simplicial 2D */
277175d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
277275d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
277375d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
277475d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
277575d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
277675d3a19aSMatthew G. Knepley         ++m;
277775d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
277875d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
277975d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
278075d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
278175d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
278275d3a19aSMatthew G. Knepley         ++m;
278375d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
278475d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
278575d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
278675d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
278775d3a19aSMatthew G. Knepley         }
278875d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
278975d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
279075d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
279175d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
279275d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
279375d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
279475d3a19aSMatthew G. Knepley         }
279575d3a19aSMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
279675d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*3     + r;
279775d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r;
279875d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
279975d3a19aSMatthew G. Knepley         }
280075d3a19aSMatthew G. Knepley       }
280175d3a19aSMatthew G. Knepley       break;
280275d3a19aSMatthew G. Knepley     case 2:
280375d3a19aSMatthew G. Knepley       /* Hex 2D */
280475d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
280575d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
280675d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
280775d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
280875d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
280975d3a19aSMatthew G. Knepley         ++m;
281075d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
281175d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
281275d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
281375d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
281475d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
281575d3a19aSMatthew G. Knepley         ++m;
281675d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
281775d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
281875d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
281975d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
282075d3a19aSMatthew G. Knepley         }
282175d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
2822455d6cd4SMatthew G. Knepley         /* Old cells add new cells, interior faces, and vertex */
282375d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
282475d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
282575d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
282675d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
282775d3a19aSMatthew G. Knepley         }
282875d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
282975d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*4     + r;
283075d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r;
283175d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
283275d3a19aSMatthew G. Knepley         }
2833455d6cd4SMatthew G. Knepley         for (r = 0; r < 1; ++r, ++m) {
2834455d6cd4SMatthew G. Knepley           localPointsNew[m]        = vStartNew     + (fEnd - fStart)                    + (p  - cStart)     + r;
2835455d6cd4SMatthew G. Knepley           remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]) + r;
2836455d6cd4SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
2837455d6cd4SMatthew G. Knepley         }
283875d3a19aSMatthew G. Knepley       }
283975d3a19aSMatthew G. Knepley       break;
284075d3a19aSMatthew G. Knepley     case 3:
284175d3a19aSMatthew G. Knepley       /* Hybrid simplicial 2D */
284275d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
284375d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
284475d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
284575d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
284675d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
284775d3a19aSMatthew G. Knepley         ++m;
284875d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fMax)) {
284975d3a19aSMatthew G. Knepley         /* Old interior faces add new faces and vertex */
285075d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
285175d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
285275d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
285375d3a19aSMatthew G. Knepley         ++m;
285475d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
285575d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
285675d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
285775d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
285875d3a19aSMatthew G. Knepley         }
285975d3a19aSMatthew G. Knepley       } else if ((p >= fMax) && (p < fEnd)) {
286075d3a19aSMatthew G. Knepley         /* Old hybrid faces stay the same */
286175d3a19aSMatthew G. Knepley         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - fMax);
286275d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
286375d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
286475d3a19aSMatthew G. Knepley         ++m;
286575d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cMax)) {
286675d3a19aSMatthew G. Knepley         /* Old interior cells add new cells and interior faces */
286775d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
286875d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
286975d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
287075d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
287175d3a19aSMatthew G. Knepley         }
287275d3a19aSMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
287375d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - cStart)*3     + r;
287475d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r;
287575d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
287675d3a19aSMatthew G. Knepley         }
287775d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cMax)) {
287875d3a19aSMatthew G. Knepley         /* Old hybrid cells add new cells and hybrid face */
287975d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
288075d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
288175d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
288275d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
288375d3a19aSMatthew G. Knepley         }
288475d3a19aSMatthew G. Knepley         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (cMax                            - cStart)*3     + (p  - cMax);
288575d3a19aSMatthew 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]);
288675d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
288775d3a19aSMatthew G. Knepley         ++m;
288875d3a19aSMatthew G. Knepley       }
288975d3a19aSMatthew G. Knepley       break;
2890b5da9499SMatthew G. Knepley     case 5:
2891b5da9499SMatthew G. Knepley       /* Simplicial 3D */
2892b5da9499SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
2893b5da9499SMatthew G. Knepley         /* Old vertices stay the same */
2894b5da9499SMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
2895b5da9499SMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
2896b5da9499SMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
2897b5da9499SMatthew G. Knepley         ++m;
289887fe6628SMatthew G. Knepley       } else if ((p >= eStart) && (p < eEnd)) {
2899b5da9499SMatthew G. Knepley         /* Old edges add new edges and vertex */
2900b5da9499SMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
2901b5da9499SMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
2902b5da9499SMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
2903b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
2904b5da9499SMatthew G. Knepley         }
2905b5da9499SMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
2906b5da9499SMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
2907b5da9499SMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
2908b5da9499SMatthew G. Knepley         ++m;
2909b5da9499SMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
2910b5da9499SMatthew G. Knepley         /* Old faces add new faces and face edges */
2911b5da9499SMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
2912b5da9499SMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
2913b5da9499SMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
2914b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
2915b5da9499SMatthew G. Knepley         }
2916b5da9499SMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
2917b5da9499SMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (p  - fStart)*3     + r;
2918b5da9499SMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + (rp - rfStart[n])*3 + r;
2919b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
2920b5da9499SMatthew G. Knepley         }
2921b5da9499SMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
2922b5da9499SMatthew G. Knepley         /* Old cells add new cells and interior faces and edges */
2923b5da9499SMatthew G. Knepley         for (r = 0; r < 8; ++r, ++m) {
2924b5da9499SMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
2925b5da9499SMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
2926b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
2927b5da9499SMatthew G. Knepley         }
2928b5da9499SMatthew G. Knepley         for (r = 0; r < 8; ++r, ++m) {
2929b5da9499SMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*4                    + (p  - cStart)*8     + r;
2930b5da9499SMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*8 + r;
2931b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
2932b5da9499SMatthew G. Knepley         }
2933b5da9499SMatthew G. Knepley         for (r = 0; r < 1; ++r, ++m) {
2934b5da9499SMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (fEnd - fStart)*3                    + (p  - cStart)*1     + r;
2935b5da9499SMatthew 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;
2936b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
2937b5da9499SMatthew G. Knepley         }
2938b5da9499SMatthew G. Knepley       }
2939b5da9499SMatthew G. Knepley       break;
29402eabf88fSMatthew G. Knepley     case 6:
29412eabf88fSMatthew G. Knepley       /* Hex 3D */
29422eabf88fSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
29432eabf88fSMatthew G. Knepley         /* Old vertices stay the same */
29442eabf88fSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
29452eabf88fSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
29462eabf88fSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
29472eabf88fSMatthew G. Knepley         ++m;
29482eabf88fSMatthew G. Knepley       } else if ((p >= eStart) && (p < eEnd)) {
29492eabf88fSMatthew G. Knepley         /* Old edges add new edges and vertex */
29502eabf88fSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
29512eabf88fSMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
29522eabf88fSMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
29532eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
29542eabf88fSMatthew G. Knepley         }
29552eabf88fSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
29562eabf88fSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
29572eabf88fSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
29582eabf88fSMatthew G. Knepley         ++m;
29592eabf88fSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
29602eabf88fSMatthew G. Knepley         /* Old faces add new faces, edges, and vertex */
29612eabf88fSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
29622eabf88fSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
29632eabf88fSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
29642eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
29652eabf88fSMatthew G. Knepley         }
29662eabf88fSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
29672eabf88fSMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (p  - fStart)*4     + r;
29682eabf88fSMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + (rp - rfStart[n])*4 + r;
29692eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
29702eabf88fSMatthew G. Knepley         }
29712eabf88fSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (eEnd - eStart)              + (p  - fStart);
29722eabf88fSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+1] + (rp - rfStart[n]);
29732eabf88fSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
29742eabf88fSMatthew G. Knepley         ++m;
29752eabf88fSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
29762eabf88fSMatthew G. Knepley         /* Old cells add new cells, faces, edges, and vertex */
29772eabf88fSMatthew G. Knepley         for (r = 0; r < 8; ++r, ++m) {
29782eabf88fSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
29792eabf88fSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
29802eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
29812eabf88fSMatthew G. Knepley         }
29822eabf88fSMatthew G. Knepley         for (r = 0; r < 12; ++r, ++m) {
29832eabf88fSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*4                    + (p  - cStart)*12     + r;
29842eabf88fSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*12 + r;
29852eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
29862eabf88fSMatthew G. Knepley         }
29872eabf88fSMatthew G. Knepley         for (r = 0; r < 6; ++r, ++m) {
29882eabf88fSMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (fEnd - fStart)*4                    + (p  - cStart)*6     + r;
29892eabf88fSMatthew 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;
29902eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
29912eabf88fSMatthew G. Knepley         }
29922eabf88fSMatthew G. Knepley         for (r = 0; r < 1; ++r, ++m) {
29932eabf88fSMatthew G. Knepley           localPointsNew[m]        = vStartNew     + (eEnd - eStart)              + (fEnd - fStart)                    + (p  - cStart)     + r;
29942eabf88fSMatthew G. Knepley           remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+1] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]) + r;
29952eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
29962eabf88fSMatthew G. Knepley         }
29972eabf88fSMatthew G. Knepley       }
29982eabf88fSMatthew G. Knepley       break;
299975d3a19aSMatthew G. Knepley     default:
300075d3a19aSMatthew G. Knepley       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
300175d3a19aSMatthew G. Knepley     }
300275d3a19aSMatthew G. Knepley   }
300375d3a19aSMatthew G. Knepley   ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr);
300475d3a19aSMatthew G. Knepley   ierr = ISDestroy(&processRanks);CHKERRQ(ierr);
300575d3a19aSMatthew G. Knepley   ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
300675d3a19aSMatthew G. Knepley   ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr);
300706a0ba2dSMatthew G. Knepley   ierr = PetscFree7(depthSizeOld,rdepthSizeOld,rdepthMaxOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr);
300875d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
300975d3a19aSMatthew G. Knepley }
301075d3a19aSMatthew G. Knepley 
301175d3a19aSMatthew G. Knepley #undef __FUNCT__
301275d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerCreateLabels"
301375d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
301475d3a19aSMatthew G. Knepley {
301575d3a19aSMatthew G. Knepley   PetscInt       numLabels, l;
3016b5da9499SMatthew G. Knepley   PetscInt       depth, newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r;
301775d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
301875d3a19aSMatthew G. Knepley 
301975d3a19aSMatthew G. Knepley   PetscFunctionBegin;
302075d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
302175d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
302275d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
302375d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
3024d963de37SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
3025d963de37SMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
302675d3a19aSMatthew G. Knepley   ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
302775d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
302875d3a19aSMatthew G. Knepley   switch (refiner) {
302975d3a19aSMatthew G. Knepley   case 3:
303075d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
303175d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
303275d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
303375d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
303475d3a19aSMatthew G. Knepley   }
303575d3a19aSMatthew G. Knepley   for (l = 0; l < numLabels; ++l) {
303675d3a19aSMatthew G. Knepley     DMLabel         label, labelNew;
303775d3a19aSMatthew G. Knepley     const char     *lname;
303875d3a19aSMatthew G. Knepley     PetscBool       isDepth;
303975d3a19aSMatthew G. Knepley     IS              valueIS;
304075d3a19aSMatthew G. Knepley     const PetscInt *values;
304175d3a19aSMatthew G. Knepley     PetscInt        numValues, val;
304275d3a19aSMatthew G. Knepley 
304375d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr);
304475d3a19aSMatthew G. Knepley     ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr);
304575d3a19aSMatthew G. Knepley     if (isDepth) continue;
304675d3a19aSMatthew G. Knepley     ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr);
304775d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr);
304875d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr);
304975d3a19aSMatthew G. Knepley     ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
305075d3a19aSMatthew G. Knepley     ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr);
305175d3a19aSMatthew G. Knepley     ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
305275d3a19aSMatthew G. Knepley     for (val = 0; val < numValues; ++val) {
305375d3a19aSMatthew G. Knepley       IS              pointIS;
305475d3a19aSMatthew G. Knepley       const PetscInt *points;
305575d3a19aSMatthew G. Knepley       PetscInt        numPoints, n;
305675d3a19aSMatthew G. Knepley 
305775d3a19aSMatthew G. Knepley       ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr);
305875d3a19aSMatthew G. Knepley       ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
305975d3a19aSMatthew G. Knepley       ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
306075d3a19aSMatthew G. Knepley       for (n = 0; n < numPoints; ++n) {
306175d3a19aSMatthew G. Knepley         const PetscInt p = points[n];
306275d3a19aSMatthew G. Knepley         switch (refiner) {
306375d3a19aSMatthew G. Knepley         case 1:
306475d3a19aSMatthew G. Knepley           /* Simplicial 2D */
306575d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
306675d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
306775d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
306875d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
306975d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
307075d3a19aSMatthew G. Knepley             /* Old faces add new faces and vertex */
307175d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
307275d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
307375d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
307475d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
307575d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
307675d3a19aSMatthew G. Knepley             }
307775d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
307875d3a19aSMatthew G. Knepley             /* Old cells add new cells and interior faces */
307975d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
308075d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
308175d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
308275d3a19aSMatthew G. Knepley             }
308375d3a19aSMatthew G. Knepley             for (r = 0; r < 3; ++r) {
308475d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
308575d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
308675d3a19aSMatthew G. Knepley             }
308775d3a19aSMatthew G. Knepley           }
308875d3a19aSMatthew G. Knepley           break;
308975d3a19aSMatthew G. Knepley         case 2:
309075d3a19aSMatthew G. Knepley           /* Hex 2D */
309175d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
309275d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
309375d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
309475d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
309575d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
309675d3a19aSMatthew G. Knepley             /* Old faces add new faces and vertex */
309775d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
309875d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
309975d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
310075d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
310175d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
310275d3a19aSMatthew G. Knepley             }
310375d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
310475d3a19aSMatthew G. Knepley             /* Old cells add new cells and interior faces and vertex */
310575d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
310675d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
310775d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
310875d3a19aSMatthew G. Knepley             }
310975d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
311075d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
311175d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
311275d3a19aSMatthew G. Knepley             }
311375d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
311475d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
311575d3a19aSMatthew G. Knepley           }
311675d3a19aSMatthew G. Knepley           break;
311775d3a19aSMatthew G. Knepley         case 3:
311875d3a19aSMatthew G. Knepley           /* Hybrid simplicial 2D */
311975d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
312075d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
312175d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
312275d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
312375d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fMax)) {
312475d3a19aSMatthew G. Knepley             /* Old interior faces add new faces and vertex */
312575d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
312675d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
312775d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
312875d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
312975d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
313075d3a19aSMatthew G. Knepley             }
313175d3a19aSMatthew G. Knepley           } else if ((p >= fMax) && (p < fEnd)) {
313275d3a19aSMatthew G. Knepley             /* Old hybrid faces stay the same */
313375d3a19aSMatthew G. Knepley             newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
313475d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
313575d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cMax)) {
313675d3a19aSMatthew G. Knepley             /* Old interior cells add new cells and interior faces */
313775d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
313875d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
313975d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
314075d3a19aSMatthew G. Knepley             }
314175d3a19aSMatthew G. Knepley             for (r = 0; r < 3; ++r) {
314275d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
314375d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
314475d3a19aSMatthew G. Knepley             }
314575d3a19aSMatthew G. Knepley           } else if ((p >= cMax) && (p < cEnd)) {
314675d3a19aSMatthew G. Knepley             /* Old hybrid cells add new cells and hybrid face */
314775d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
314875d3a19aSMatthew G. Knepley               newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
314975d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
315075d3a19aSMatthew G. Knepley             }
315175d3a19aSMatthew G. Knepley             newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
315275d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
315375d3a19aSMatthew G. Knepley           }
315475d3a19aSMatthew G. Knepley           break;
3155b5da9499SMatthew G. Knepley         case 5:
3156b5da9499SMatthew G. Knepley           /* Simplicial 3D */
3157b5da9499SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
3158b5da9499SMatthew G. Knepley             /* Old vertices stay the same */
3159b5da9499SMatthew G. Knepley             newp = vStartNew + (p - vStart);
3160b5da9499SMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3161b5da9499SMatthew G. Knepley           } else if ((p >= eStart) && (p < eEnd)) {
3162b5da9499SMatthew G. Knepley             /* Old edges add new edges and vertex */
3163b5da9499SMatthew G. Knepley             for (r = 0; r < 2; ++r) {
3164b5da9499SMatthew G. Knepley               newp = eStartNew + (p - eStart)*2 + r;
3165b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3166b5da9499SMatthew G. Knepley             }
3167b5da9499SMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - eStart);
3168b5da9499SMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3169b5da9499SMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
3170b5da9499SMatthew G. Knepley             /* Old faces add new faces and edges */
3171b5da9499SMatthew G. Knepley             for (r = 0; r < 4; ++r) {
3172b5da9499SMatthew G. Knepley               newp = fStartNew + (p - fStart)*4 + r;
3173b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3174b5da9499SMatthew G. Knepley             }
3175b5da9499SMatthew G. Knepley             for (r = 0; r < 3; ++r) {
3176b5da9499SMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
3177b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3178b5da9499SMatthew G. Knepley             }
3179b5da9499SMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
3180b5da9499SMatthew G. Knepley             /* Old cells add new cells and interior faces and edges */
3181b5da9499SMatthew G. Knepley             for (r = 0; r < 8; ++r) {
3182b5da9499SMatthew G. Knepley               newp = cStartNew + (p - cStart)*8 + r;
3183b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3184b5da9499SMatthew G. Knepley             }
3185b5da9499SMatthew G. Knepley             for (r = 0; r < 8; ++r) {
3186b5da9499SMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*8 + r;
3187b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3188b5da9499SMatthew G. Knepley             }
3189b5da9499SMatthew G. Knepley             for (r = 0; r < 1; ++r) {
3190b5da9499SMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*1 + r;
3191b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
3192b5da9499SMatthew G. Knepley             }
3193b5da9499SMatthew G. Knepley           }
3194b5da9499SMatthew G. Knepley           break;
31952eabf88fSMatthew G. Knepley         case 6:
31962eabf88fSMatthew G. Knepley           /* Hex 3D */
31972eabf88fSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
31982eabf88fSMatthew G. Knepley             /* Old vertices stay the same */
31992eabf88fSMatthew G. Knepley             newp = vStartNew + (p - vStart);
32002eabf88fSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
32012eabf88fSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
32022eabf88fSMatthew G. Knepley             /* Old edges add new edges and vertex */
32032eabf88fSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
32042eabf88fSMatthew G. Knepley               newp = eStartNew + (p - eStart)*2 + r;
32052eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
32062eabf88fSMatthew G. Knepley             }
32072eabf88fSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - eStart);
32082eabf88fSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
32092eabf88fSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
32102eabf88fSMatthew G. Knepley             /* Old faces add new faces, edges, and vertex */
32112eabf88fSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
32122eabf88fSMatthew G. Knepley               newp = fStartNew + (p - fStart)*4 + r;
32132eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
32142eabf88fSMatthew G. Knepley             }
32152eabf88fSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
32162eabf88fSMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*4 + r;
32172eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
32182eabf88fSMatthew G. Knepley             }
32192eabf88fSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (p - fStart);
32202eabf88fSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
32212eabf88fSMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
32222eabf88fSMatthew G. Knepley             /* Old cells add new cells, faces, edges, and vertex */
32232eabf88fSMatthew G. Knepley             for (r = 0; r < 8; ++r) {
32242eabf88fSMatthew G. Knepley               newp = cStartNew + (p - cStart)*8 + r;
32252eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
32262eabf88fSMatthew G. Knepley             }
32272eabf88fSMatthew G. Knepley             for (r = 0; r < 12; ++r) {
32282eabf88fSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*12 + r;
32292eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
32302eabf88fSMatthew G. Knepley             }
32312eabf88fSMatthew G. Knepley             for (r = 0; r < 6; ++r) {
32322eabf88fSMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (p - cStart)*6 + r;
32332eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
32342eabf88fSMatthew G. Knepley             }
32352eabf88fSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (p - cStart);
32362eabf88fSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
32372eabf88fSMatthew G. Knepley           }
32382eabf88fSMatthew G. Knepley           break;
323975d3a19aSMatthew G. Knepley         default:
324075d3a19aSMatthew G. Knepley           SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
324175d3a19aSMatthew G. Knepley         }
324275d3a19aSMatthew G. Knepley       }
324375d3a19aSMatthew G. Knepley       ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
324475d3a19aSMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
324575d3a19aSMatthew G. Knepley     }
324675d3a19aSMatthew G. Knepley     ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
324775d3a19aSMatthew G. Knepley     ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
324875d3a19aSMatthew G. Knepley     if (0) {
324975d3a19aSMatthew G. Knepley       ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr);
325075d3a19aSMatthew G. Knepley       ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
325175d3a19aSMatthew G. Knepley       ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
325275d3a19aSMatthew G. Knepley     }
325375d3a19aSMatthew G. Knepley   }
325475d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
325575d3a19aSMatthew G. Knepley }
325675d3a19aSMatthew G. Knepley 
325775d3a19aSMatthew G. Knepley #undef __FUNCT__
3258509c9b89SMatthew G. Knepley #define __FUNCT__ "DMPlexRefineUniform_Internal"
325975d3a19aSMatthew G. Knepley /* This will only work for interpolated meshes */
3260509c9b89SMatthew G. Knepley PetscErrorCode DMPlexRefineUniform_Internal(DM dm, CellRefiner cellRefiner, DM *dmRefined)
326175d3a19aSMatthew G. Knepley {
326275d3a19aSMatthew G. Knepley   DM             rdm;
326375d3a19aSMatthew G. Knepley   PetscInt      *depthSize;
326475d3a19aSMatthew G. Knepley   PetscInt       dim, depth = 0, d, pStart = 0, pEnd = 0;
326575d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
326675d3a19aSMatthew G. Knepley 
326775d3a19aSMatthew G. Knepley   PetscFunctionBegin;
326875d3a19aSMatthew G. Knepley   ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr);
326975d3a19aSMatthew G. Knepley   ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr);
327075d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
327175d3a19aSMatthew G. Knepley   ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr);
327275d3a19aSMatthew G. Knepley   /* Calculate number of new points of each depth */
327375d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
327475d3a19aSMatthew G. Knepley   ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr);
327575d3a19aSMatthew G. Knepley   ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr);
327675d3a19aSMatthew G. Knepley   ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr);
327775d3a19aSMatthew G. Knepley   /* Step 1: Set chart */
327875d3a19aSMatthew G. Knepley   for (d = 0; d <= depth; ++d) pEnd += depthSize[d];
327975d3a19aSMatthew G. Knepley   ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr);
328075d3a19aSMatthew G. Knepley   /* Step 2: Set cone/support sizes */
328175d3a19aSMatthew G. Knepley   ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
328275d3a19aSMatthew G. Knepley   /* Step 3: Setup refined DM */
328375d3a19aSMatthew G. Knepley   ierr = DMSetUp(rdm);CHKERRQ(ierr);
328475d3a19aSMatthew G. Knepley   /* Step 4: Set cones and supports */
328575d3a19aSMatthew G. Knepley   ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
328675d3a19aSMatthew G. Knepley   /* Step 5: Stratify */
328775d3a19aSMatthew G. Knepley   ierr = DMPlexStratify(rdm);CHKERRQ(ierr);
328875d3a19aSMatthew G. Knepley   /* Step 6: Set coordinates for vertices */
328975d3a19aSMatthew G. Knepley   ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
329075d3a19aSMatthew G. Knepley   /* Step 7: Create pointSF */
329175d3a19aSMatthew G. Knepley   ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
329275d3a19aSMatthew G. Knepley   /* Step 8: Create labels */
329375d3a19aSMatthew G. Knepley   ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
329475d3a19aSMatthew G. Knepley   ierr = PetscFree(depthSize);CHKERRQ(ierr);
329575d3a19aSMatthew G. Knepley 
329675d3a19aSMatthew G. Knepley   *dmRefined = rdm;
329775d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
329875d3a19aSMatthew G. Knepley }
329975d3a19aSMatthew G. Knepley 
330075d3a19aSMatthew G. Knepley #undef __FUNCT__
330175d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexSetRefinementUniform"
330275d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
330375d3a19aSMatthew G. Knepley {
330475d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
330575d3a19aSMatthew G. Knepley 
330675d3a19aSMatthew G. Knepley   PetscFunctionBegin;
330775d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
330875d3a19aSMatthew G. Knepley   mesh->refinementUniform = refinementUniform;
330975d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
331075d3a19aSMatthew G. Knepley }
331175d3a19aSMatthew G. Knepley 
331275d3a19aSMatthew G. Knepley #undef __FUNCT__
331375d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexGetRefinementUniform"
331475d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
331575d3a19aSMatthew G. Knepley {
331675d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
331775d3a19aSMatthew G. Knepley 
331875d3a19aSMatthew G. Knepley   PetscFunctionBegin;
331975d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
332075d3a19aSMatthew G. Knepley   PetscValidPointer(refinementUniform,  2);
332175d3a19aSMatthew G. Knepley   *refinementUniform = mesh->refinementUniform;
332275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
332375d3a19aSMatthew G. Knepley }
332475d3a19aSMatthew G. Knepley 
332575d3a19aSMatthew G. Knepley #undef __FUNCT__
332675d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexSetRefinementLimit"
332775d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
332875d3a19aSMatthew G. Knepley {
332975d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
333075d3a19aSMatthew G. Knepley 
333175d3a19aSMatthew G. Knepley   PetscFunctionBegin;
333275d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
333375d3a19aSMatthew G. Knepley   mesh->refinementLimit = refinementLimit;
333475d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
333575d3a19aSMatthew G. Knepley }
333675d3a19aSMatthew G. Knepley 
333775d3a19aSMatthew G. Knepley #undef __FUNCT__
333875d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexGetRefinementLimit"
333975d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
334075d3a19aSMatthew G. Knepley {
334175d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
334275d3a19aSMatthew G. Knepley 
334375d3a19aSMatthew G. Knepley   PetscFunctionBegin;
334475d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
334575d3a19aSMatthew G. Knepley   PetscValidPointer(refinementLimit,  2);
334675d3a19aSMatthew G. Knepley   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
334775d3a19aSMatthew G. Knepley   *refinementLimit = mesh->refinementLimit;
334875d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
334975d3a19aSMatthew G. Knepley }
335075d3a19aSMatthew G. Knepley 
335175d3a19aSMatthew G. Knepley #undef __FUNCT__
3352509c9b89SMatthew G. Knepley #define __FUNCT__ "DMPlexGetCellRefiner_Internal"
3353509c9b89SMatthew G. Knepley PetscErrorCode DMPlexGetCellRefiner_Internal(DM dm, CellRefiner *cellRefiner)
335475d3a19aSMatthew G. Knepley {
335575d3a19aSMatthew G. Knepley   PetscInt       dim, cStart, coneSize, cMax;
335675d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
335775d3a19aSMatthew G. Knepley 
335875d3a19aSMatthew G. Knepley   PetscFunctionBegin;
335975d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
336075d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr);
336175d3a19aSMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr);
336275d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr);
336375d3a19aSMatthew G. Knepley   switch (dim) {
336475d3a19aSMatthew G. Knepley   case 2:
336575d3a19aSMatthew G. Knepley     switch (coneSize) {
336675d3a19aSMatthew G. Knepley     case 3:
336775d3a19aSMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 3; /* Hybrid */
336875d3a19aSMatthew G. Knepley       else *cellRefiner = 1; /* Triangular */
336975d3a19aSMatthew G. Knepley       break;
337075d3a19aSMatthew G. Knepley     case 4:
337175d3a19aSMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 4; /* Hybrid */
337275d3a19aSMatthew G. Knepley       else *cellRefiner = 2; /* Quadrilateral */
337375d3a19aSMatthew G. Knepley       break;
337475d3a19aSMatthew G. Knepley     default:
337575d3a19aSMatthew G. Knepley       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
337675d3a19aSMatthew G. Knepley     }
337775d3a19aSMatthew G. Knepley     break;
3378b5da9499SMatthew G. Knepley   case 3:
3379b5da9499SMatthew G. Knepley     switch (coneSize) {
3380b5da9499SMatthew G. Knepley     case 4:
3381b5da9499SMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 7; /* Hybrid */
3382b5da9499SMatthew G. Knepley       else *cellRefiner = 5; /* Tetrahedral */
3383b5da9499SMatthew G. Knepley       break;
33842eabf88fSMatthew G. Knepley     case 6:
33852eabf88fSMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 8; /* Hybrid */
33862eabf88fSMatthew G. Knepley       else *cellRefiner = 6; /* hexahedral */
33872eabf88fSMatthew G. Knepley       break;
3388b5da9499SMatthew G. Knepley     default:
3389b5da9499SMatthew G. Knepley       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
3390b5da9499SMatthew G. Knepley     }
3391b5da9499SMatthew G. Knepley     break;
339275d3a19aSMatthew G. Knepley   default:
339375d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim);
339475d3a19aSMatthew G. Knepley   }
339575d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
339675d3a19aSMatthew G. Knepley }
3397