xref: /petsc/src/dm/impls/plex/plexrefine.c (revision c3a233c89d5344b97fcee0623834fc4bdafb4eb7)
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__
2975d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerGetSizes"
3075d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[])
3175d3a19aSMatthew G. Knepley {
326ce3c06aSMatthew G. Knepley   PetscInt       cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax;
3375d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
3475d3a19aSMatthew G. Knepley 
3575d3a19aSMatthew G. Knepley   PetscFunctionBegin;
3675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
3775d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
3875d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
3975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
4075d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
4175d3a19aSMatthew G. Knepley   switch (refiner) {
423478d7aaSMatthew G. Knepley   case 0:
433478d7aaSMatthew G. Knepley     break;
4475d3a19aSMatthew G. Knepley   case 1:
4575d3a19aSMatthew G. Knepley     /* Simplicial 2D */
4675d3a19aSMatthew G. Knepley     depthSize[0] = vEnd - vStart + fEnd - fStart;         /* Add a vertex on every face */
4775d3a19aSMatthew 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 */
4875d3a19aSMatthew G. Knepley     depthSize[2] = 4*(cEnd - cStart);                     /* Every cell split into 4 cells */
4975d3a19aSMatthew G. Knepley     break;
5075d3a19aSMatthew G. Knepley   case 3:
51d963de37SMatthew G. Knepley     /* Hybrid Simplicial 2D */
5275d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
5375d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
5475d3a19aSMatthew G. Knepley     depthSize[0] = vEnd - vStart + fMax - fStart;                                         /* Add a vertex on every face, but not hybrid faces */
5575d3a19aSMatthew 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 */
5675d3a19aSMatthew G. Knepley     depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax);                                   /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */
5775d3a19aSMatthew G. Knepley     break;
5875d3a19aSMatthew G. Knepley   case 2:
5975d3a19aSMatthew G. Knepley     /* Hex 2D */
6075d3a19aSMatthew G. Knepley     depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */
6175d3a19aSMatthew 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 */
6275d3a19aSMatthew G. Knepley     depthSize[2] = 4*(cEnd - cStart);                             /* Every cell split into 4 cells */
6375d3a19aSMatthew G. Knepley     break;
64b5da9499SMatthew G. Knepley   case 5:
65b5da9499SMatthew G. Knepley     /* Simplicial 3D */
66b5da9499SMatthew G. Knepley     depthSize[0] =    vEnd - vStart  +    eEnd - eStart;                    /* Add a vertex on every edge */
67b5da9499SMatthew 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 */
68b5da9499SMatthew G. Knepley     depthSize[2] = 4*(fEnd - fStart) + 8*(cEnd - cStart);                   /* Every face split into 4 faces and 8 faces are added for each cell */
69b5da9499SMatthew G. Knepley     depthSize[3] = 8*(cEnd - cStart);                                       /* Every cell split into 8 cells */
70b5da9499SMatthew G. Knepley     break;
71b5da9499SMatthew G. Knepley   case 7:
72b5da9499SMatthew G. Knepley     /* Hybrid Simplicial 3D */
73b5da9499SMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
746ce3c06aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
75b5da9499SMatthew G. Knepley     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
76dae4404aSMatthew G. Knepley     /* Tetrahedra */
77dae4404aSMatthew G. Knepley     depthSize[0]  =    vEnd - vStart  +    eMax - eStart;                    /* Add a vertex on every interior edge */
78dae4404aSMatthew G. Knepley     depthSize[1]  = 2*(eMax - eStart) + 3*(fMax - fStart) + (cMax - cStart); /* Every interior edge split into 2 edges, 3 edges added for each interior face, 1 edge for each interior cell */
79dae4404aSMatthew G. Knepley     depthSize[2]  = 4*(fMax - fStart) + 8*(cMax - cStart);                   /* Every interior face split into 4 faces, 8 faces added for each interior cell */
80dae4404aSMatthew G. Knepley     depthSize[3]  = 8*(cMax - cStart);                                       /* Every interior cell split into 8 cells */
81dae4404aSMatthew G. Knepley     /* Triangular Prisms */
82dae4404aSMatthew G. Knepley     depthSize[0] += 0;                                                       /* No hybrid vertices */
83dae4404aSMatthew G. Knepley     depthSize[1] +=   (eEnd - eMax)   +   (fEnd - fMax);                     /* Every hybrid edge remains, 1 edge for every hybrid face */
846ce3c06aSMatthew G. Knepley     depthSize[2] += 2*(fEnd - fMax)   + 3*(cEnd - cMax);                     /* Every hybrid face split into 2 faces and 3 faces are added for each hybrid cell */
85dae4404aSMatthew G. Knepley     depthSize[3] += 4*(cEnd - cMax);                                         /* Every hybrid cell split into 4 cells */
86b5da9499SMatthew G. Knepley     break;
876ce3c06aSMatthew G. Knepley   case 6:
886ce3c06aSMatthew G. Knepley     /* Hex 3D */
896ce3c06aSMatthew G. Knepley     depthSize[0] = vEnd - vStart + eEnd - eStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every edge, face and cell */
906ce3c06aSMatthew 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 */
916ce3c06aSMatthew 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 */
926ce3c06aSMatthew G. Knepley     depthSize[3] = 8*(cEnd - cStart);                                             /* Every cell split into 8 cells */
936ce3c06aSMatthew G. Knepley     break;
9475d3a19aSMatthew G. Knepley   default:
9575d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
9675d3a19aSMatthew G. Knepley   }
9775d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
9875d3a19aSMatthew G. Knepley }
9975d3a19aSMatthew G. Knepley 
10042525629SMatthew G. Knepley /* Return triangle edge for orientation o, if it is r for o == 0 */
10142525629SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetTriEdge_Static(PetscInt o, PetscInt r) {
102518a8359SMatthew G. Knepley   return (o < 0 ? 2-(o+r) : o+r)%3;
103518a8359SMatthew G. Knepley }
104de65f515SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetTriEdgeInverse_Static(PetscInt o, PetscInt s) {
105de65f515SMatthew G. Knepley   return (o < 0 ? 2-(o+s) : 3+s-o)%3;
106de65f515SMatthew G. Knepley }
107518a8359SMatthew G. Knepley 
108518a8359SMatthew G. Knepley /* Return triangle subface for orientation o, if it is r for o == 0 */
109518a8359SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetTriSubface_Static(PetscInt o, PetscInt r) {
1104bae88c7SMatthew G. Knepley   return (o < 0 ? 3-(o+r) : o+r)%3;
11142525629SMatthew G. Knepley }
112de65f515SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetTriSubfaceInverse_Static(PetscInt o, PetscInt s) {
113de65f515SMatthew G. Knepley   return (o < 0 ? 3-(o+s) : 3+s-o)%3;
114de65f515SMatthew G. Knepley }
11542525629SMatthew G. Knepley 
116e3f8b1d6SMatthew G. Knepley /* Return quad edge for orientation o, if it is r for o == 0 */
117e3f8b1d6SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetQuadEdge_Static(PetscInt o, PetscInt r) {
118e3f8b1d6SMatthew G. Knepley   return (o < 0 ? 3-(o+r) : o+r)%4;
119e3f8b1d6SMatthew G. Knepley }
120e3f8b1d6SMatthew G. Knepley 
121e3f8b1d6SMatthew G. Knepley /* Return quad subface for orientation o, if it is r for o == 0 */
122e3f8b1d6SMatthew G. Knepley PETSC_STATIC_INLINE PetscInt GetQuadSubface_Static(PetscInt o, PetscInt r) {
1234bae88c7SMatthew G. Knepley   return (o < 0 ? 4-(o+r) : o+r)%4;
12442525629SMatthew G. Knepley }
12542525629SMatthew G. Knepley 
12675d3a19aSMatthew G. Knepley #undef __FUNCT__
12775d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetConeSizes"
12875d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
12975d3a19aSMatthew G. Knepley {
130b5da9499SMatthew 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;
13175d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
13275d3a19aSMatthew G. Knepley 
13375d3a19aSMatthew G. Knepley   PetscFunctionBegin;
13475d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
13575d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
13675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
13775d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
13875d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
13975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
1403478d7aaSMatthew G. Knepley   if (refiner) {ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);}
14175d3a19aSMatthew G. Knepley   switch (refiner) {
1423478d7aaSMatthew G. Knepley   case 0: break;
14375d3a19aSMatthew G. Knepley   case 1:
14475d3a19aSMatthew G. Knepley     /* Simplicial 2D */
14575d3a19aSMatthew G. Knepley     /* All cells have 3 faces */
14675d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
14775d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
14875d3a19aSMatthew G. Knepley         const PetscInt newp = (c - cStart)*4 + r;
14975d3a19aSMatthew G. Knepley 
15075d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
15175d3a19aSMatthew G. Knepley       }
15275d3a19aSMatthew G. Knepley     }
15375d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
15475d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
15575d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
15675d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
15775d3a19aSMatthew G. Knepley         PetscInt       size;
15875d3a19aSMatthew G. Knepley 
15975d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
16075d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
16175d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
16275d3a19aSMatthew G. Knepley       }
16375d3a19aSMatthew G. Knepley     }
16475d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
16575d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
16675d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
16775d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
16875d3a19aSMatthew G. Knepley 
16975d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
17075d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
17175d3a19aSMatthew G. Knepley       }
17275d3a19aSMatthew G. Knepley     }
17375d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
17475d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
17575d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
17675d3a19aSMatthew G. Knepley       PetscInt       size;
17775d3a19aSMatthew G. Knepley 
17875d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
17975d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
18075d3a19aSMatthew G. Knepley     }
18175d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells*2 supports */
18275d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
18375d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
18475d3a19aSMatthew G. Knepley       PetscInt       size;
18575d3a19aSMatthew G. Knepley 
18675d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
18775d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr);
18875d3a19aSMatthew G. Knepley     }
18975d3a19aSMatthew G. Knepley     break;
19075d3a19aSMatthew G. Knepley   case 2:
19175d3a19aSMatthew G. Knepley     /* Hex 2D */
19275d3a19aSMatthew G. Knepley     /* All cells have 4 faces */
19375d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
19475d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
19575d3a19aSMatthew G. Knepley         const PetscInt newp = (c - cStart)*4 + r;
19675d3a19aSMatthew G. Knepley 
19775d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
19875d3a19aSMatthew G. Knepley       }
19975d3a19aSMatthew G. Knepley     }
20075d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
20175d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
20275d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
20375d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
20475d3a19aSMatthew G. Knepley         PetscInt       size;
20575d3a19aSMatthew G. Knepley 
20675d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
20775d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
20875d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
20975d3a19aSMatthew G. Knepley       }
21075d3a19aSMatthew G. Knepley     }
21175d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
21275d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
21375d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
21475d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
21575d3a19aSMatthew G. Knepley 
21675d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
21775d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
21875d3a19aSMatthew G. Knepley       }
21975d3a19aSMatthew G. Knepley     }
22075d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
22175d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
22275d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
22375d3a19aSMatthew G. Knepley       PetscInt       size;
22475d3a19aSMatthew G. Knepley 
22575d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
22675d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
22775d3a19aSMatthew G. Knepley     }
22875d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells supports */
22975d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
23075d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
23175d3a19aSMatthew G. Knepley       PetscInt       size;
23275d3a19aSMatthew G. Knepley 
23375d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
23475d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
23575d3a19aSMatthew G. Knepley     }
23675d3a19aSMatthew G. Knepley     /* Cell vertices have 4 supports */
23775d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
23875d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
23975d3a19aSMatthew G. Knepley 
24075d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
24175d3a19aSMatthew G. Knepley     }
24275d3a19aSMatthew G. Knepley     break;
24375d3a19aSMatthew G. Knepley   case 3:
244d963de37SMatthew G. Knepley     /* Hybrid Simplicial 2D */
24575d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
24675d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
24775d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
24875d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
24975d3a19aSMatthew G. Knepley     ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
25075d3a19aSMatthew G. Knepley     /* Interior cells have 3 faces */
25175d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
25275d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
25375d3a19aSMatthew G. Knepley         const PetscInt newp = cStartNew + (c - cStart)*4 + r;
25475d3a19aSMatthew G. Knepley 
25575d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
25675d3a19aSMatthew G. Knepley       }
25775d3a19aSMatthew G. Knepley     }
25875d3a19aSMatthew G. Knepley     /* Hybrid cells have 4 faces */
25975d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
26075d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
26175d3a19aSMatthew G. Knepley         const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
26275d3a19aSMatthew G. Knepley 
26375d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
26475d3a19aSMatthew G. Knepley       }
26575d3a19aSMatthew G. Knepley     }
26675d3a19aSMatthew G. Knepley     /* Interior split faces have 2 vertices and the same cells as the parent */
26775d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
26875d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
26975d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
27075d3a19aSMatthew G. Knepley         PetscInt       size;
27175d3a19aSMatthew G. Knepley 
27275d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
27375d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
27475d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
27575d3a19aSMatthew G. Knepley       }
27675d3a19aSMatthew G. Knepley     }
27775d3a19aSMatthew G. Knepley     /* Interior cell faces have 2 vertices and 2 cells */
27875d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
27975d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
28075d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
28175d3a19aSMatthew G. Knepley 
28275d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
28375d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
28475d3a19aSMatthew G. Knepley       }
28575d3a19aSMatthew G. Knepley     }
28675d3a19aSMatthew G. Knepley     /* Hybrid faces have 2 vertices and the same cells */
28775d3a19aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
28875d3a19aSMatthew G. Knepley       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
28975d3a19aSMatthew G. Knepley       PetscInt       size;
29075d3a19aSMatthew G. Knepley 
29175d3a19aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
29275d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
29375d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
29475d3a19aSMatthew G. Knepley     }
29575d3a19aSMatthew G. Knepley     /* Hybrid cell faces have 2 vertices and 2 cells */
29675d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
29775d3a19aSMatthew G. Knepley       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
29875d3a19aSMatthew G. Knepley 
29975d3a19aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
30075d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
30175d3a19aSMatthew G. Knepley     }
30275d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
30375d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
30475d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
30575d3a19aSMatthew G. Knepley       PetscInt       size;
30675d3a19aSMatthew G. Knepley 
30775d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
30875d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
30975d3a19aSMatthew G. Knepley     }
31075d3a19aSMatthew G. Knepley     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
31175d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
31275d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
31375d3a19aSMatthew G. Knepley       const PetscInt *support;
31475d3a19aSMatthew G. Knepley       PetscInt       size, newSize = 2, s;
31575d3a19aSMatthew G. Knepley 
31675d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
31775d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
31875d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
31975d3a19aSMatthew G. Knepley         if (support[s] >= cMax) newSize += 1;
32075d3a19aSMatthew G. Knepley         else newSize += 2;
32175d3a19aSMatthew G. Knepley       }
32275d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr);
32375d3a19aSMatthew G. Knepley     }
32475d3a19aSMatthew G. Knepley     break;
325b5da9499SMatthew G. Knepley   case 5:
326b5da9499SMatthew G. Knepley     /* Simplicial 3D */
327b5da9499SMatthew G. Knepley     /* All cells have 4 faces */
328b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
329b5da9499SMatthew G. Knepley       for (r = 0; r < 8; ++r) {
330dae4404aSMatthew G. Knepley         const PetscInt newp = cStartNew + (c - cStart)*8 + r;
331b5da9499SMatthew G. Knepley 
332b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
333b5da9499SMatthew G. Knepley       }
334b5da9499SMatthew G. Knepley     }
335b5da9499SMatthew G. Knepley     /* Split faces have 3 edges and the same cells as the parent */
336b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
337b5da9499SMatthew G. Knepley       for (r = 0; r < 4; ++r) {
338b5da9499SMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
339b5da9499SMatthew G. Knepley         PetscInt       size;
340b5da9499SMatthew G. Knepley 
341b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
342b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
343b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
344b5da9499SMatthew G. Knepley       }
345b5da9499SMatthew G. Knepley     }
346b5da9499SMatthew G. Knepley     /* Interior faces have 3 edges and 2 cells */
347b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
348b5da9499SMatthew G. Knepley       for (r = 0; r < 8; ++r) {
349b5da9499SMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + r;
350b5da9499SMatthew G. Knepley 
351b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
352b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
353b5da9499SMatthew G. Knepley       }
354b5da9499SMatthew G. Knepley     }
355b5da9499SMatthew G. Knepley     /* Split edges have 2 vertices and the same faces */
356b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
357b5da9499SMatthew G. Knepley       for (r = 0; r < 2; ++r) {
358b5da9499SMatthew G. Knepley         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
359b5da9499SMatthew G. Knepley         PetscInt       size;
360b5da9499SMatthew G. Knepley 
361b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
362b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
363b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
364b5da9499SMatthew G. Knepley       }
365b5da9499SMatthew G. Knepley     }
366b5da9499SMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
367b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
368b5da9499SMatthew G. Knepley       for (r = 0; r < 3; ++r) {
369b5da9499SMatthew G. Knepley         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
370b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
371b5da9499SMatthew G. Knepley         PetscInt        coneSize, c, supportSize, s, er, intFaces = 0;
372b5da9499SMatthew G. Knepley 
373b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
374b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
375b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
376b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
377b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
378b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
379b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
380b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
38186f0afeeSMatthew G. Knepley           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
38286f0afeeSMatthew G. Knepley           er = ornt[c] < 0 ? (-(ornt[c]+1) + 2-r)%3 : (ornt[c] + r)%3;
383b5da9499SMatthew G. Knepley           if (er == eint[c]) {
384b5da9499SMatthew G. Knepley             intFaces += 1;
385b5da9499SMatthew G. Knepley           } else {
386b5da9499SMatthew G. Knepley             intFaces += 2;
387b5da9499SMatthew G. Knepley           }
388b5da9499SMatthew G. Knepley         }
389b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2+intFaces);CHKERRQ(ierr);
390b5da9499SMatthew G. Knepley       }
391b5da9499SMatthew G. Knepley     }
392b5da9499SMatthew G. Knepley     /* Interior edges have 2 vertices and 4 faces */
393b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
394b5da9499SMatthew G. Knepley       const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
395b5da9499SMatthew G. Knepley 
396b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
397b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
398b5da9499SMatthew G. Knepley     }
399b5da9499SMatthew G. Knepley     /* Old vertices have identical supports */
400b5da9499SMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
401b5da9499SMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
402b5da9499SMatthew G. Knepley       PetscInt       size;
403b5da9499SMatthew G. Knepley 
404b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
405b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
406b5da9499SMatthew G. Knepley     }
407b5da9499SMatthew G. Knepley     /* Edge vertices have 2 + faces*2 + cells*0/1 supports */
408b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
409b5da9499SMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
410b5da9499SMatthew G. Knepley       PetscInt       size, *star = NULL, starSize, s, cellSize = 0;
411b5da9499SMatthew G. Knepley 
412b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
413b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
414b5da9499SMatthew G. Knepley       for (s = 0; s < starSize*2; s += 2) {
415b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt;
416b5da9499SMatthew G. Knepley         PetscInt        e01, e23;
417b5da9499SMatthew G. Knepley 
418b5da9499SMatthew G. Knepley         if ((star[s] >= cStart) && (star[s] < cEnd)) {
419b5da9499SMatthew G. Knepley           /* Check edge 0-1 */
420b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
421b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
422b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
42342525629SMatthew G. Knepley           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
424b5da9499SMatthew G. Knepley           /* Check edge 2-3 */
425b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
426b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
42742525629SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
42842525629SMatthew G. Knepley           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
429b5da9499SMatthew G. Knepley           if ((e01 == e) || (e23 == e)) ++cellSize;
430b5da9499SMatthew G. Knepley         }
431b5da9499SMatthew G. Knepley       }
432b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
433b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2 + cellSize);CHKERRQ(ierr);
434b5da9499SMatthew G. Knepley     }
435b5da9499SMatthew G. Knepley     break;
436dae4404aSMatthew G. Knepley   case 7:
4376ce3c06aSMatthew G. Knepley     /* Hybrid Simplicial 3D */
4386ce3c06aSMatthew G. Knepley     ierr = DMPlexSetHybridBounds(rdm, cStartNew + 8*(cMax-cStart), fStartNew + 4*(fMax - fStart) + 8*(cMax - cStart),
4396ce3c06aSMatthew G. Knepley                                  eStartNew + 2*(eMax - eStart) + 3*(fMax - fStart) + (cMax - cStart), PETSC_DETERMINE);CHKERRQ(ierr);
440dae4404aSMatthew G. Knepley     /* Interior cells have 4 faces */
441dae4404aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
442dae4404aSMatthew G. Knepley       for (r = 0; r < 8; ++r) {
443dae4404aSMatthew G. Knepley         const PetscInt newp = cStartNew + (c - cStart)*8 + r;
444dae4404aSMatthew G. Knepley 
445dae4404aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
446dae4404aSMatthew G. Knepley       }
447dae4404aSMatthew G. Knepley     }
448dae4404aSMatthew G. Knepley     /* Hybrid cells have 5 faces */
449dae4404aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
450dae4404aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
451dae4404aSMatthew G. Knepley         const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;
452dae4404aSMatthew G. Knepley 
453dae4404aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 5);CHKERRQ(ierr);
454dae4404aSMatthew G. Knepley       }
455dae4404aSMatthew G. Knepley     }
4566ce3c06aSMatthew G. Knepley     /* Interior split faces have 3 edges and the same cells as the parent */
457dae4404aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
458dae4404aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
459dae4404aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
460dae4404aSMatthew G. Knepley         PetscInt       size;
461dae4404aSMatthew G. Knepley 
462dae4404aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
463dae4404aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
464dae4404aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
465dae4404aSMatthew G. Knepley       }
466dae4404aSMatthew G. Knepley     }
467dae4404aSMatthew G. Knepley     /* Interior cell faces have 3 edges and 2 cells */
468dae4404aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
469dae4404aSMatthew G. Knepley       for (r = 0; r < 8; ++r) {
470dae4404aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + r;
471dae4404aSMatthew G. Knepley 
472dae4404aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
473dae4404aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
474dae4404aSMatthew G. Knepley       }
475dae4404aSMatthew G. Knepley     }
4766ce3c06aSMatthew G. Knepley     /* Hybrid split faces have 4 edges and the same cells as the parent */
4776ce3c06aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
4786ce3c06aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
4796ce3c06aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;
4806ce3c06aSMatthew G. Knepley         PetscInt       size;
4816ce3c06aSMatthew G. Knepley 
4826ce3c06aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
4836ce3c06aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
4846ce3c06aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
4856ce3c06aSMatthew G. Knepley       }
4866ce3c06aSMatthew G. Knepley     }
4876ce3c06aSMatthew G. Knepley     /* Hybrid cells faces have 4 edges and 2 cells */
4886ce3c06aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
4896ce3c06aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
4906ce3c06aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + r;
4916ce3c06aSMatthew G. Knepley 
4926ce3c06aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
4936ce3c06aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
4946ce3c06aSMatthew G. Knepley       }
4956ce3c06aSMatthew G. Knepley     }
4966ce3c06aSMatthew G. Knepley     /* Interior split edges have 2 vertices and the same faces */
497dae4404aSMatthew G. Knepley     for (e = eStart; e < eMax; ++e) {
498dae4404aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
499dae4404aSMatthew G. Knepley         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
500dae4404aSMatthew G. Knepley         PetscInt       size;
501dae4404aSMatthew G. Knepley 
502dae4404aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
503dae4404aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
504dae4404aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
505dae4404aSMatthew G. Knepley       }
506dae4404aSMatthew G. Knepley     }
5076ce3c06aSMatthew G. Knepley     /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
508dae4404aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
509dae4404aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
510dae4404aSMatthew G. Knepley         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
511dae4404aSMatthew G. Knepley         const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
512dae4404aSMatthew G. Knepley         PetscInt        coneSize, c, supportSize, s, er, intFaces = 0;
513dae4404aSMatthew G. Knepley 
514dae4404aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
515dae4404aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
516dae4404aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
517dae4404aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
518dae4404aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
519dae4404aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
520dae4404aSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
521dae4404aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
5226ce3c06aSMatthew G. Knepley           if (support[s] < cMax) {
523dae4404aSMatthew G. Knepley             /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
524dae4404aSMatthew G. Knepley             er = ornt[c] < 0 ? (-(ornt[c]+1) + 2-r)%3 : (ornt[c] + r)%3;
525dae4404aSMatthew G. Knepley             if (er == eint[c]) {
526dae4404aSMatthew G. Knepley               intFaces += 1;
527dae4404aSMatthew G. Knepley             } else {
528dae4404aSMatthew G. Knepley               intFaces += 2;
529dae4404aSMatthew G. Knepley             }
5306ce3c06aSMatthew G. Knepley           } else {
5316ce3c06aSMatthew G. Knepley             intFaces += 1;
5326ce3c06aSMatthew G. Knepley           }
533dae4404aSMatthew G. Knepley         }
534dae4404aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2+intFaces);CHKERRQ(ierr);
535dae4404aSMatthew G. Knepley       }
536dae4404aSMatthew G. Knepley     }
5376ce3c06aSMatthew G. Knepley     /* Interior cell edges have 2 vertices and 4 faces */
538dae4404aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
539dae4404aSMatthew G. Knepley       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
540dae4404aSMatthew G. Knepley 
541dae4404aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
542dae4404aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
543dae4404aSMatthew G. Knepley     }
5446ce3c06aSMatthew G. Knepley     /* Hybrid edges have 2 vertices and the same faces */
545dae4404aSMatthew G. Knepley     for (e = eMax; e < eEnd; ++e) {
5466ce3c06aSMatthew G. Knepley       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
5476ce3c06aSMatthew G. Knepley       PetscInt       size;
5486ce3c06aSMatthew G. Knepley 
5496ce3c06aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
5506ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
5516ce3c06aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
5526ce3c06aSMatthew G. Knepley     }
5536ce3c06aSMatthew G. Knepley     /* Hybrid face edges have 2 vertices and 2+2*cells faces */
5546ce3c06aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
5556ce3c06aSMatthew G. Knepley       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
556dae4404aSMatthew G. Knepley       PetscInt       size;
557dae4404aSMatthew G. Knepley 
558dae4404aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
559dae4404aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
5606ce3c06aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2+2*size);CHKERRQ(ierr);
561dae4404aSMatthew G. Knepley     }
5626ce3c06aSMatthew G. Knepley     /* Interior vertices have identical supports */
563dae4404aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
564dae4404aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
565dae4404aSMatthew G. Knepley       PetscInt       size;
566dae4404aSMatthew G. Knepley 
567dae4404aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
568dae4404aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
569dae4404aSMatthew G. Knepley     }
5706ce3c06aSMatthew G. Knepley     /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
5716ce3c06aSMatthew G. Knepley     for (e = eStart; e < eMax; ++e) {
5726ce3c06aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
573dae4404aSMatthew G. Knepley       const PetscInt *support;
5746ce3c06aSMatthew G. Knepley       PetscInt        size, *star = NULL, starSize, s, faceSize = 0, cellSize = 0;
575dae4404aSMatthew G. Knepley 
5766ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
5776ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
578dae4404aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
5796ce3c06aSMatthew G. Knepley         if (support[s] < fMax) faceSize += 2;
5806ce3c06aSMatthew G. Knepley         else                   faceSize += 1;
581dae4404aSMatthew G. Knepley       }
5826ce3c06aSMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
5836ce3c06aSMatthew G. Knepley       for (s = 0; s < starSize*2; s += 2) {
5846ce3c06aSMatthew G. Knepley         const PetscInt *cone, *ornt;
5856ce3c06aSMatthew G. Knepley         PetscInt        e01, e23;
5866ce3c06aSMatthew G. Knepley 
5876ce3c06aSMatthew G. Knepley         if ((star[s] >= cStart) && (star[s] < cMax)) {
5886ce3c06aSMatthew G. Knepley           /* Check edge 0-1 */
5896ce3c06aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
5906ce3c06aSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
5916ce3c06aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
5926ce3c06aSMatthew G. Knepley           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
5936ce3c06aSMatthew G. Knepley           /* Check edge 2-3 */
5946ce3c06aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
5956ce3c06aSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
5966ce3c06aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
5976ce3c06aSMatthew G. Knepley           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
5986ce3c06aSMatthew G. Knepley           if ((e01 == e) || (e23 == e)) ++cellSize;
5996ce3c06aSMatthew G. Knepley         }
6006ce3c06aSMatthew G. Knepley       }
6016ce3c06aSMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
6026ce3c06aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + faceSize + cellSize);CHKERRQ(ierr);
603dae4404aSMatthew G. Knepley     }
604dae4404aSMatthew G. Knepley     break;
6052eabf88fSMatthew G. Knepley   case 6:
6062eabf88fSMatthew G. Knepley     /* Hex 3D */
6072eabf88fSMatthew G. Knepley     /* All cells have 6 faces */
6082eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
6092eabf88fSMatthew G. Knepley       for (r = 0; r < 8; ++r) {
6102eabf88fSMatthew G. Knepley         const PetscInt newp = (c - cStart)*8 + r;
6112eabf88fSMatthew G. Knepley 
6122eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 6);CHKERRQ(ierr);
6132eabf88fSMatthew G. Knepley       }
6142eabf88fSMatthew G. Knepley     }
6152eabf88fSMatthew G. Knepley     /* Split faces have 4 edges and the same cells as the parent */
6162eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
6172eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
6182eabf88fSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
6192eabf88fSMatthew G. Knepley         PetscInt       size;
6202eabf88fSMatthew G. Knepley 
6212eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
6222eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
6232eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
6242eabf88fSMatthew G. Knepley       }
6252eabf88fSMatthew G. Knepley     }
6262eabf88fSMatthew G. Knepley     /* Interior faces have 4 edges and 2 cells */
6272eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
6282eabf88fSMatthew G. Knepley       for (r = 0; r < 12; ++r) {
6292eabf88fSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
6302eabf88fSMatthew G. Knepley 
6312eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
6322eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
6332eabf88fSMatthew G. Knepley       }
6342eabf88fSMatthew G. Knepley     }
6352eabf88fSMatthew G. Knepley     /* Split edges have 2 vertices and the same faces as the parent */
6362eabf88fSMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
6372eabf88fSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
6382eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
6392eabf88fSMatthew G. Knepley         PetscInt       size;
6402eabf88fSMatthew G. Knepley 
6412eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
6422eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
6432eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
6442eabf88fSMatthew G. Knepley       }
6452eabf88fSMatthew G. Knepley     }
6462eabf88fSMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells faces */
6472eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
6482eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
6492eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
6502eabf88fSMatthew G. Knepley         PetscInt       size;
6512eabf88fSMatthew G. Knepley 
6522eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
6532eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
6542eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2+size);CHKERRQ(ierr);
6552eabf88fSMatthew G. Knepley       }
6562eabf88fSMatthew G. Knepley     }
6572eabf88fSMatthew G. Knepley     /* Cell edges have 2 vertices and 4 faces */
6582eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
6592eabf88fSMatthew G. Knepley       for (r = 0; r < 6; ++r) {
6602eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
6612eabf88fSMatthew G. Knepley 
6622eabf88fSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
6632eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
6642eabf88fSMatthew G. Knepley       }
6652eabf88fSMatthew G. Knepley     }
6662eabf88fSMatthew G. Knepley     /* Old vertices have identical supports */
6672eabf88fSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
6682eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
6692eabf88fSMatthew G. Knepley       PetscInt       size;
6702eabf88fSMatthew G. Knepley 
6712eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
6722eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
6732eabf88fSMatthew G. Knepley     }
6742eabf88fSMatthew G. Knepley     /* Edge vertices have 2 + faces supports */
6752eabf88fSMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
6762eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
6772eabf88fSMatthew G. Knepley       PetscInt       size;
6782eabf88fSMatthew G. Knepley 
6792eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
6802eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
6812eabf88fSMatthew G. Knepley     }
6822eabf88fSMatthew G. Knepley     /* Face vertices have 4 + cells supports */
6832eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
6842eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
6852eabf88fSMatthew G. Knepley       PetscInt       size;
6862eabf88fSMatthew G. Knepley 
6872eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
6882eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4 + size);CHKERRQ(ierr);
6892eabf88fSMatthew G. Knepley     }
6902eabf88fSMatthew G. Knepley     /* Cell vertices have 6 supports */
6912eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
6922eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
6932eabf88fSMatthew G. Knepley 
6942eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 6);CHKERRQ(ierr);
6952eabf88fSMatthew G. Knepley     }
6962eabf88fSMatthew G. Knepley     break;
69775d3a19aSMatthew G. Knepley   default:
69875d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
69975d3a19aSMatthew G. Knepley   }
70075d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
70175d3a19aSMatthew G. Knepley }
70275d3a19aSMatthew G. Knepley 
70375d3a19aSMatthew G. Knepley #undef __FUNCT__
70475d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetCones"
70575d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
70675d3a19aSMatthew G. Knepley {
707b5da9499SMatthew G. Knepley   const PetscInt *faces, cellInd[4] = {0, 1, 2, 3};
7086ce3c06aSMatthew G. Knepley   PetscInt        cStart,    cEnd,    cMax,    vStart,    vEnd, vMax, fStart,    fEnd,    fMax,    eStart,    eEnd,    eMax;
7096ce3c06aSMatthew G. Knepley   PetscInt        cStartNew, cEndNew, cMaxNew, vStartNew, vEndNew,    fStartNew, fEndNew, fMaxNew, eStartNew, eEndNew, eMaxNew;
7106ce3c06aSMatthew G. Knepley   PetscInt        depth, maxSupportSize, *supportRef, c, f, e, v, r, p;
71175d3a19aSMatthew G. Knepley   PetscErrorCode  ierr;
71275d3a19aSMatthew G. Knepley 
71375d3a19aSMatthew G. Knepley   PetscFunctionBegin;
71475d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
71575d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
71675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
71775d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
71875d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
71975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
7203478d7aaSMatthew G. Knepley   if (refiner) {
72175d3a19aSMatthew G. Knepley     ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
72275d3a19aSMatthew G. Knepley     ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr);
7233478d7aaSMatthew G. Knepley   }
72475d3a19aSMatthew G. Knepley   switch (refiner) {
7253478d7aaSMatthew G. Knepley   case 0: break;
72675d3a19aSMatthew G. Knepley   case 1:
72775d3a19aSMatthew G. Knepley     /* Simplicial 2D */
72875d3a19aSMatthew G. Knepley     /*
72975d3a19aSMatthew G. Knepley      2
73075d3a19aSMatthew G. Knepley      |\
73175d3a19aSMatthew G. Knepley      | \
73275d3a19aSMatthew G. Knepley      |  \
73375d3a19aSMatthew G. Knepley      |   \
73475d3a19aSMatthew G. Knepley      | C  \
73575d3a19aSMatthew G. Knepley      |     \
73675d3a19aSMatthew G. Knepley      |      \
73775d3a19aSMatthew G. Knepley      2---1---1
73875d3a19aSMatthew G. Knepley      |\  D  / \
73975d3a19aSMatthew G. Knepley      | 2   0   \
74075d3a19aSMatthew G. Knepley      |A \ /  B  \
74175d3a19aSMatthew G. Knepley      0---0-------1
74275d3a19aSMatthew G. Knepley      */
74375d3a19aSMatthew G. Knepley     /* All cells have 3 faces */
74475d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
74575d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*4;
74675d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
74775d3a19aSMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
74875d3a19aSMatthew G. Knepley 
74975d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
75075d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
75175d3a19aSMatthew G. Knepley       /* A triangle */
75275d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
75375d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
75475d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
75575d3a19aSMatthew G. Knepley       orntNew[1] = -2;
75675d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
75775d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
75875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
75975d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
76075d3a19aSMatthew G. Knepley #if 1
76175d3a19aSMatthew 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);
76275d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
76375d3a19aSMatthew 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);
76475d3a19aSMatthew G. Knepley       }
76575d3a19aSMatthew G. Knepley #endif
76675d3a19aSMatthew G. Knepley       /* B triangle */
76775d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
76875d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
76975d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
77075d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
77175d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
77275d3a19aSMatthew G. Knepley       orntNew[2] = -2;
77375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
77475d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
77575d3a19aSMatthew G. Knepley #if 1
77675d3a19aSMatthew 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);
77775d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
77875d3a19aSMatthew 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);
77975d3a19aSMatthew G. Knepley       }
78075d3a19aSMatthew G. Knepley #endif
78175d3a19aSMatthew G. Knepley       /* C triangle */
78275d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
78375d3a19aSMatthew G. Knepley       orntNew[0] = -2;
78475d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
78575d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
78675d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
78775d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
78875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
78975d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
79075d3a19aSMatthew G. Knepley #if 1
79175d3a19aSMatthew 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);
79275d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
79375d3a19aSMatthew 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);
79475d3a19aSMatthew G. Knepley       }
79575d3a19aSMatthew G. Knepley #endif
79675d3a19aSMatthew G. Knepley       /* D triangle */
79775d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
79875d3a19aSMatthew G. Knepley       orntNew[0] = 0;
79975d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
80075d3a19aSMatthew G. Knepley       orntNew[1] = 0;
80175d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
80275d3a19aSMatthew G. Knepley       orntNew[2] = 0;
80375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
80475d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
80575d3a19aSMatthew G. Knepley #if 1
80675d3a19aSMatthew 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);
80775d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
80875d3a19aSMatthew 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);
80975d3a19aSMatthew G. Knepley       }
81075d3a19aSMatthew G. Knepley #endif
81175d3a19aSMatthew G. Knepley     }
81275d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
81375d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
81475d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
81575d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
81675d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
81775d3a19aSMatthew G. Knepley 
81875d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
81975d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
820297d2bf4SMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
82175d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
82275d3a19aSMatthew G. Knepley 
82375d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
82475d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
82575d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
82675d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
82775d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
82875d3a19aSMatthew G. Knepley #if 1
82975d3a19aSMatthew 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);
83075d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
83175d3a19aSMatthew 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);
83275d3a19aSMatthew G. Knepley         }
83375d3a19aSMatthew G. Knepley #endif
83475d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
83575d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
83675d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
83775d3a19aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
83875d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
839297d2bf4SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
84075d3a19aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
84175d3a19aSMatthew G. Knepley             if (cone[c] == f) break;
84275d3a19aSMatthew G. Knepley           }
843297d2bf4SMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
84475d3a19aSMatthew G. Knepley         }
84575d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
84675d3a19aSMatthew G. Knepley #if 1
84775d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
84875d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
84975d3a19aSMatthew 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);
85075d3a19aSMatthew G. Knepley         }
85175d3a19aSMatthew G. Knepley #endif
85275d3a19aSMatthew G. Knepley       }
85375d3a19aSMatthew G. Knepley     }
85475d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
85575d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
85675d3a19aSMatthew G. Knepley       const PetscInt *cone;
85775d3a19aSMatthew G. Knepley 
85875d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
85975d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
86075d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
86175d3a19aSMatthew G. Knepley         PetscInt       coneNew[2];
86275d3a19aSMatthew G. Knepley         PetscInt       supportNew[2];
86375d3a19aSMatthew G. Knepley 
86475d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
86575d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
86675d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
86775d3a19aSMatthew G. Knepley #if 1
86875d3a19aSMatthew 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);
86975d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
87075d3a19aSMatthew 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);
87175d3a19aSMatthew G. Knepley         }
87275d3a19aSMatthew G. Knepley #endif
87375d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + (r+1)%3;
87475d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + 3;
87575d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
87675d3a19aSMatthew G. Knepley #if 1
87775d3a19aSMatthew 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);
87875d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
87975d3a19aSMatthew 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);
88075d3a19aSMatthew G. Knepley         }
88175d3a19aSMatthew G. Knepley #endif
88275d3a19aSMatthew G. Knepley       }
88375d3a19aSMatthew G. Knepley     }
88475d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
88575d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
88675d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
88775d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
88875d3a19aSMatthew G. Knepley       PetscInt        size, s;
88975d3a19aSMatthew G. Knepley 
89075d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
89175d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
89275d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
89375d3a19aSMatthew G. Knepley         PetscInt r = 0;
89475d3a19aSMatthew G. Knepley 
89575d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
89675d3a19aSMatthew G. Knepley         if (cone[1] == v) r = 1;
89775d3a19aSMatthew G. Knepley         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
89875d3a19aSMatthew G. Knepley       }
89975d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
90075d3a19aSMatthew G. Knepley #if 1
90175d3a19aSMatthew 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);
90275d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
90375d3a19aSMatthew 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);
90475d3a19aSMatthew G. Knepley       }
90575d3a19aSMatthew G. Knepley #endif
90675d3a19aSMatthew G. Knepley     }
90775d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells*2 supports */
90875d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
90975d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
91075d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
91175d3a19aSMatthew G. Knepley       PetscInt        size, s;
91275d3a19aSMatthew G. Knepley 
91375d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
91475d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
91575d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
91675d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
91775d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
91875d3a19aSMatthew G. Knepley         PetscInt r = 0;
91975d3a19aSMatthew G. Knepley 
92075d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
92175d3a19aSMatthew G. Knepley         if      (cone[1] == f) r = 1;
92275d3a19aSMatthew G. Knepley         else if (cone[2] == f) r = 2;
92375d3a19aSMatthew G. Knepley         supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
92475d3a19aSMatthew G. Knepley         supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
92575d3a19aSMatthew G. Knepley       }
92675d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
92775d3a19aSMatthew G. Knepley #if 1
92875d3a19aSMatthew 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);
92975d3a19aSMatthew G. Knepley       for (p = 0; p < 2+size*2; ++p) {
93075d3a19aSMatthew 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);
93175d3a19aSMatthew G. Knepley       }
93275d3a19aSMatthew G. Knepley #endif
93375d3a19aSMatthew G. Knepley     }
93475d3a19aSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
93575d3a19aSMatthew G. Knepley     break;
93675d3a19aSMatthew G. Knepley   case 2:
93775d3a19aSMatthew G. Knepley     /* Hex 2D */
93875d3a19aSMatthew G. Knepley     /*
93975d3a19aSMatthew G. Knepley      3---------2---------2
94075d3a19aSMatthew G. Knepley      |         |         |
94175d3a19aSMatthew G. Knepley      |    D    2    C    |
94275d3a19aSMatthew G. Knepley      |         |         |
94375d3a19aSMatthew G. Knepley      3----3----0----1----1
94475d3a19aSMatthew G. Knepley      |         |         |
94575d3a19aSMatthew G. Knepley      |    A    0    B    |
94675d3a19aSMatthew G. Knepley      |         |         |
94775d3a19aSMatthew G. Knepley      0---------0---------1
94875d3a19aSMatthew G. Knepley      */
94975d3a19aSMatthew G. Knepley     /* All cells have 4 faces */
95075d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
95175d3a19aSMatthew G. Knepley       const PetscInt  newp = (c - cStart)*4;
95275d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
95375d3a19aSMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
95475d3a19aSMatthew G. Knepley 
95575d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
95675d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
95775d3a19aSMatthew G. Knepley       /* A quad */
95875d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
95975d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
96075d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
96175d3a19aSMatthew G. Knepley       orntNew[1] = 0;
96275d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
96375d3a19aSMatthew G. Knepley       orntNew[2] = -2;
96475d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
96575d3a19aSMatthew G. Knepley       orntNew[3] = ornt[3];
96675d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
96775d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
96875d3a19aSMatthew G. Knepley #if 1
96975d3a19aSMatthew 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);
97075d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
97175d3a19aSMatthew 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);
97275d3a19aSMatthew G. Knepley       }
97375d3a19aSMatthew G. Knepley #endif
97475d3a19aSMatthew G. Knepley       /* B quad */
97575d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
97675d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
97775d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
97875d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
97975d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
98075d3a19aSMatthew G. Knepley       orntNew[2] = 0;
98175d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
98275d3a19aSMatthew G. Knepley       orntNew[3] = -2;
98375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
98475d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
98575d3a19aSMatthew G. Knepley #if 1
98675d3a19aSMatthew 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);
98775d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
98875d3a19aSMatthew 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);
98975d3a19aSMatthew G. Knepley       }
99075d3a19aSMatthew G. Knepley #endif
99175d3a19aSMatthew G. Knepley       /* C quad */
99275d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
99375d3a19aSMatthew G. Knepley       orntNew[0] = -2;
99475d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
99575d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
99675d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
99775d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
99875d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
99975d3a19aSMatthew G. Knepley       orntNew[3] = 0;
100075d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
100175d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
100275d3a19aSMatthew G. Knepley #if 1
100375d3a19aSMatthew 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);
100475d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
100575d3a19aSMatthew 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);
100675d3a19aSMatthew G. Knepley       }
100775d3a19aSMatthew G. Knepley #endif
100875d3a19aSMatthew G. Knepley       /* D quad */
100975d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
101075d3a19aSMatthew G. Knepley       orntNew[0] = 0;
101175d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
101275d3a19aSMatthew G. Knepley       orntNew[1] = -2;
101375d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
101475d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
101575d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
101675d3a19aSMatthew G. Knepley       orntNew[3] = ornt[3];
101775d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
101875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
101975d3a19aSMatthew G. Knepley #if 1
102075d3a19aSMatthew 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);
102175d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
102275d3a19aSMatthew 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);
102375d3a19aSMatthew G. Knepley       }
102475d3a19aSMatthew G. Knepley #endif
102575d3a19aSMatthew G. Knepley     }
102675d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
102775d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
102875d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
102975d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
103075d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
103175d3a19aSMatthew G. Knepley 
103275d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
103375d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
1034455d6cd4SMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
103575d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
103675d3a19aSMatthew G. Knepley 
103775d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
103875d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
103975d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
104075d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
104175d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
104275d3a19aSMatthew G. Knepley #if 1
104375d3a19aSMatthew 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);
104475d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
104575d3a19aSMatthew 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);
104675d3a19aSMatthew G. Knepley         }
104775d3a19aSMatthew G. Knepley #endif
104875d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
104975d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
105075d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
105175d3a19aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
105275d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1053455d6cd4SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
105475d3a19aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
105575d3a19aSMatthew G. Knepley             if (cone[c] == f) break;
105675d3a19aSMatthew G. Knepley           }
1057455d6cd4SMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
105875d3a19aSMatthew G. Knepley         }
105975d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
106075d3a19aSMatthew G. Knepley #if 1
106175d3a19aSMatthew 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);
106275d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
106375d3a19aSMatthew 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);
106475d3a19aSMatthew G. Knepley         }
106575d3a19aSMatthew G. Knepley #endif
106675d3a19aSMatthew G. Knepley       }
106775d3a19aSMatthew G. Knepley     }
106875d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
106975d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
107075d3a19aSMatthew G. Knepley       const PetscInt *cone;
107175d3a19aSMatthew G. Knepley       PetscInt        coneNew[2], supportNew[2];
107275d3a19aSMatthew G. Knepley 
107375d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
107475d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
107575d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
107675d3a19aSMatthew G. Knepley 
107775d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
107875d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
107975d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
108075d3a19aSMatthew G. Knepley #if 1
108175d3a19aSMatthew 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);
108275d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
108375d3a19aSMatthew 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);
108475d3a19aSMatthew G. Knepley         }
108575d3a19aSMatthew G. Knepley #endif
108675d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + r;
108775d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + (r+1)%4;
108875d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
108975d3a19aSMatthew G. Knepley #if 1
109075d3a19aSMatthew 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);
109175d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
109275d3a19aSMatthew 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);
109375d3a19aSMatthew G. Knepley         }
109475d3a19aSMatthew G. Knepley #endif
109575d3a19aSMatthew G. Knepley       }
109675d3a19aSMatthew G. Knepley     }
109775d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
109875d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
109975d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
110075d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
110175d3a19aSMatthew G. Knepley       PetscInt        size, s;
110275d3a19aSMatthew G. Knepley 
110375d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
110475d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
110575d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
110675d3a19aSMatthew G. Knepley         PetscInt r = 0;
110775d3a19aSMatthew G. Knepley 
110875d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
110975d3a19aSMatthew G. Knepley         if (cone[1] == v) r = 1;
111075d3a19aSMatthew G. Knepley         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
111175d3a19aSMatthew G. Knepley       }
111275d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
111375d3a19aSMatthew G. Knepley #if 1
111475d3a19aSMatthew 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);
111575d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
111675d3a19aSMatthew 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);
111775d3a19aSMatthew G. Knepley       }
111875d3a19aSMatthew G. Knepley #endif
111975d3a19aSMatthew G. Knepley     }
112075d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells supports */
112175d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
112275d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
112375d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
112475d3a19aSMatthew G. Knepley       PetscInt        size, s;
112575d3a19aSMatthew G. Knepley 
112675d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
112775d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
112875d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
112975d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
113075d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
113175d3a19aSMatthew G. Knepley         PetscInt r = 0;
113275d3a19aSMatthew G. Knepley 
113375d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
113475d3a19aSMatthew G. Knepley         if      (cone[1] == f) r = 1;
113575d3a19aSMatthew G. Knepley         else if (cone[2] == f) r = 2;
113675d3a19aSMatthew G. Knepley         else if (cone[3] == f) r = 3;
113775d3a19aSMatthew G. Knepley         supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r;
113875d3a19aSMatthew G. Knepley       }
113975d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
114075d3a19aSMatthew G. Knepley #if 1
114175d3a19aSMatthew 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);
114275d3a19aSMatthew G. Knepley       for (p = 0; p < 2+size; ++p) {
114375d3a19aSMatthew 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);
114475d3a19aSMatthew G. Knepley       }
114575d3a19aSMatthew G. Knepley #endif
114675d3a19aSMatthew G. Knepley     }
114775d3a19aSMatthew G. Knepley     /* Cell vertices have 4 supports */
114875d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
114975d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
115075d3a19aSMatthew G. Knepley       PetscInt       supportNew[4];
115175d3a19aSMatthew G. Knepley 
115275d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
115375d3a19aSMatthew G. Knepley         supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
115475d3a19aSMatthew G. Knepley       }
115575d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
115675d3a19aSMatthew G. Knepley     }
1157da00770fSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
115875d3a19aSMatthew G. Knepley     break;
115975d3a19aSMatthew G. Knepley   case 3:
116075d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
116175d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
116275d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
116375d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
116475d3a19aSMatthew G. Knepley     /* Interior cells have 3 faces */
116575d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
116675d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*4;
116775d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
116875d3a19aSMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
116975d3a19aSMatthew G. Knepley 
117075d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
117175d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
117275d3a19aSMatthew G. Knepley       /* A triangle */
117375d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
117475d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
117575d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
117675d3a19aSMatthew G. Knepley       orntNew[1] = -2;
117775d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
117875d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
117975d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
118075d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
118175d3a19aSMatthew G. Knepley #if 1
118275d3a19aSMatthew 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);
118375d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
118475d3a19aSMatthew 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);
118575d3a19aSMatthew G. Knepley       }
118675d3a19aSMatthew G. Knepley #endif
118775d3a19aSMatthew G. Knepley       /* B triangle */
118875d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
118975d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
119075d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
119175d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
119275d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
119375d3a19aSMatthew G. Knepley       orntNew[2] = -2;
119475d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
119575d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
119675d3a19aSMatthew G. Knepley #if 1
119775d3a19aSMatthew 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);
119875d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
119975d3a19aSMatthew 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);
120075d3a19aSMatthew G. Knepley       }
120175d3a19aSMatthew G. Knepley #endif
120275d3a19aSMatthew G. Knepley       /* C triangle */
120375d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
120475d3a19aSMatthew G. Knepley       orntNew[0] = -2;
120575d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
120675d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
120775d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
120875d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
120975d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
121075d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
121175d3a19aSMatthew G. Knepley #if 1
121275d3a19aSMatthew 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);
121375d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
121475d3a19aSMatthew 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);
121575d3a19aSMatthew G. Knepley       }
121675d3a19aSMatthew G. Knepley #endif
121775d3a19aSMatthew G. Knepley       /* D triangle */
121875d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
121975d3a19aSMatthew G. Knepley       orntNew[0] = 0;
122075d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
122175d3a19aSMatthew G. Knepley       orntNew[1] = 0;
122275d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
122375d3a19aSMatthew G. Knepley       orntNew[2] = 0;
122475d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
122575d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
122675d3a19aSMatthew G. Knepley #if 1
122775d3a19aSMatthew 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);
122875d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
122975d3a19aSMatthew 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);
123075d3a19aSMatthew G. Knepley       }
123175d3a19aSMatthew G. Knepley #endif
123275d3a19aSMatthew G. Knepley     }
123375d3a19aSMatthew G. Knepley     /*
123475d3a19aSMatthew G. Knepley      2----3----3
123575d3a19aSMatthew G. Knepley      |         |
123675d3a19aSMatthew G. Knepley      |    B    |
123775d3a19aSMatthew G. Knepley      |         |
123875d3a19aSMatthew G. Knepley      0----4--- 1
123975d3a19aSMatthew G. Knepley      |         |
124075d3a19aSMatthew G. Knepley      |    A    |
124175d3a19aSMatthew G. Knepley      |         |
124275d3a19aSMatthew G. Knepley      0----2----1
124375d3a19aSMatthew G. Knepley      */
124475d3a19aSMatthew G. Knepley     /* Hybrid cells have 4 faces */
124575d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
124675d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
124775d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
124875d3a19aSMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
124975d3a19aSMatthew G. Knepley 
125075d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
125175d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
125275d3a19aSMatthew G. Knepley       /* A quad */
125375d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
125475d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
125575d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
125675d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
125775d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax);
125875d3a19aSMatthew G. Knepley       orntNew[2] = 0;
125975d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
126075d3a19aSMatthew G. Knepley       orntNew[3] = 0;
126175d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
126275d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
126375d3a19aSMatthew G. Knepley #if 1
126475d3a19aSMatthew 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);
126575d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
126675d3a19aSMatthew 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);
126775d3a19aSMatthew G. Knepley       }
126875d3a19aSMatthew G. Knepley #endif
126975d3a19aSMatthew G. Knepley       /* B quad */
127075d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
127175d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
127275d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
127375d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
127475d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
127575d3a19aSMatthew G. Knepley       orntNew[2] = 0;
127675d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax);
127775d3a19aSMatthew G. Knepley       orntNew[3] = 0;
127875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
127975d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
128075d3a19aSMatthew G. Knepley #if 1
128175d3a19aSMatthew 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);
128275d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
128375d3a19aSMatthew 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);
128475d3a19aSMatthew G. Knepley       }
128575d3a19aSMatthew G. Knepley #endif
128675d3a19aSMatthew G. Knepley     }
128775d3a19aSMatthew G. Knepley     /* Interior split faces have 2 vertices and the same cells as the parent */
128875d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
128975d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
129075d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
129175d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
129275d3a19aSMatthew G. Knepley 
129375d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
129475d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
1295297d2bf4SMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
129675d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
129775d3a19aSMatthew G. Knepley 
129875d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
129975d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
130075d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
130175d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
130275d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
130375d3a19aSMatthew G. Knepley #if 1
130475d3a19aSMatthew 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);
130575d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
130675d3a19aSMatthew 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);
130775d3a19aSMatthew G. Knepley         }
130875d3a19aSMatthew G. Knepley #endif
130975d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
131075d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
131175d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
131275d3a19aSMatthew G. Knepley           if (support[s] >= cMax) {
131375d3a19aSMatthew G. Knepley             supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
131475d3a19aSMatthew G. Knepley           } else {
131575d3a19aSMatthew G. Knepley             ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
131675d3a19aSMatthew G. Knepley             ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1317297d2bf4SMatthew G. Knepley             ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
131875d3a19aSMatthew G. Knepley             for (c = 0; c < coneSize; ++c) {
131975d3a19aSMatthew G. Knepley               if (cone[c] == f) break;
132075d3a19aSMatthew G. Knepley             }
1321297d2bf4SMatthew G. Knepley             supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
132275d3a19aSMatthew G. Knepley           }
132375d3a19aSMatthew G. Knepley         }
132475d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
132575d3a19aSMatthew G. Knepley #if 1
132675d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
132775d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
132875d3a19aSMatthew 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);
132975d3a19aSMatthew G. Knepley         }
133075d3a19aSMatthew G. Knepley #endif
133175d3a19aSMatthew G. Knepley       }
133275d3a19aSMatthew G. Knepley     }
133375d3a19aSMatthew G. Knepley     /* Interior cell faces have 2 vertices and 2 cells */
133475d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
133575d3a19aSMatthew G. Knepley       const PetscInt *cone;
133675d3a19aSMatthew G. Knepley 
133775d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
133875d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
133975d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
134075d3a19aSMatthew G. Knepley         PetscInt       coneNew[2];
134175d3a19aSMatthew G. Knepley         PetscInt       supportNew[2];
134275d3a19aSMatthew G. Knepley 
134375d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
134475d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
134575d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
134675d3a19aSMatthew G. Knepley #if 1
134775d3a19aSMatthew 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);
134875d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
134975d3a19aSMatthew 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);
135075d3a19aSMatthew G. Knepley         }
135175d3a19aSMatthew G. Knepley #endif
135275d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + (r+1)%3;
135375d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + 3;
135475d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
135575d3a19aSMatthew G. Knepley #if 1
135675d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
135775d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
135875d3a19aSMatthew G. Knepley           if ((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);
135975d3a19aSMatthew G. Knepley         }
136075d3a19aSMatthew G. Knepley #endif
136175d3a19aSMatthew G. Knepley       }
136275d3a19aSMatthew G. Knepley     }
136375d3a19aSMatthew G. Knepley     /* Interior hybrid faces have 2 vertices and the same cells */
136475d3a19aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
136575d3a19aSMatthew G. Knepley       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
136675d3a19aSMatthew G. Knepley       const PetscInt *cone;
136775d3a19aSMatthew G. Knepley       const PetscInt *support;
136875d3a19aSMatthew G. Knepley       PetscInt        coneNew[2];
136975d3a19aSMatthew G. Knepley       PetscInt        supportNew[2];
137075d3a19aSMatthew G. Knepley       PetscInt        size, s, r;
137175d3a19aSMatthew G. Knepley 
137275d3a19aSMatthew G. Knepley       ierr       = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
137375d3a19aSMatthew G. Knepley       coneNew[0] = vStartNew + (cone[0] - vStart);
137475d3a19aSMatthew G. Knepley       coneNew[1] = vStartNew + (cone[1] - vStart);
137575d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
137675d3a19aSMatthew G. Knepley #if 1
137775d3a19aSMatthew 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);
137875d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
137975d3a19aSMatthew 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);
138075d3a19aSMatthew G. Knepley       }
138175d3a19aSMatthew G. Knepley #endif
138275d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
138375d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
138475d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
138575d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
138675d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r) {
138775d3a19aSMatthew G. Knepley           if (cone[r+2] == f) break;
138875d3a19aSMatthew G. Knepley         }
138975d3a19aSMatthew G. Knepley         supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
139075d3a19aSMatthew G. Knepley       }
139175d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
139275d3a19aSMatthew G. Knepley #if 1
139375d3a19aSMatthew 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);
139475d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
139575d3a19aSMatthew 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);
139675d3a19aSMatthew G. Knepley       }
139775d3a19aSMatthew G. Knepley #endif
139875d3a19aSMatthew G. Knepley     }
139975d3a19aSMatthew G. Knepley     /* Cell hybrid faces have 2 vertices and 2 cells */
140075d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
140175d3a19aSMatthew G. Knepley       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
140275d3a19aSMatthew G. Knepley       const PetscInt *cone;
140375d3a19aSMatthew G. Knepley       PetscInt        coneNew[2];
140475d3a19aSMatthew G. Knepley       PetscInt        supportNew[2];
140575d3a19aSMatthew G. Knepley 
140675d3a19aSMatthew G. Knepley       ierr       = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
140775d3a19aSMatthew G. Knepley       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
140875d3a19aSMatthew G. Knepley       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
140975d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
141075d3a19aSMatthew G. Knepley #if 1
141175d3a19aSMatthew 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);
141275d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
141375d3a19aSMatthew 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);
141475d3a19aSMatthew G. Knepley       }
141575d3a19aSMatthew G. Knepley #endif
141675d3a19aSMatthew G. Knepley       supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
141775d3a19aSMatthew G. Knepley       supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
141875d3a19aSMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
141975d3a19aSMatthew G. Knepley #if 1
142075d3a19aSMatthew 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);
142175d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
142275d3a19aSMatthew 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);
142375d3a19aSMatthew G. Knepley       }
142475d3a19aSMatthew G. Knepley #endif
142575d3a19aSMatthew G. Knepley     }
142675d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
142775d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
142875d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
142975d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
143075d3a19aSMatthew G. Knepley       PetscInt        size, s;
143175d3a19aSMatthew G. Knepley 
143275d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
143375d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
143475d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
143575d3a19aSMatthew G. Knepley         if (support[s] >= fMax) {
143675d3a19aSMatthew G. Knepley           supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax);
143775d3a19aSMatthew G. Knepley         } else {
143875d3a19aSMatthew G. Knepley           PetscInt r = 0;
143975d3a19aSMatthew G. Knepley 
144075d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
144175d3a19aSMatthew G. Knepley           if (cone[1] == v) r = 1;
144275d3a19aSMatthew G. Knepley           supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
144375d3a19aSMatthew G. Knepley         }
144475d3a19aSMatthew G. Knepley       }
144575d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
144675d3a19aSMatthew G. Knepley #if 1
144775d3a19aSMatthew 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);
144875d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
144975d3a19aSMatthew 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);
145075d3a19aSMatthew G. Knepley       }
145175d3a19aSMatthew G. Knepley #endif
145275d3a19aSMatthew G. Knepley     }
145375d3a19aSMatthew G. Knepley     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
145475d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
145575d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
145675d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
145775d3a19aSMatthew G. Knepley       PetscInt        size, newSize = 2, s;
145875d3a19aSMatthew G. Knepley 
145975d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
146075d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
146175d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
146275d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
146375d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
146475d3a19aSMatthew G. Knepley         PetscInt r = 0;
146575d3a19aSMatthew G. Knepley 
146675d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
146775d3a19aSMatthew G. Knepley         if (support[s] >= cMax) {
146875d3a19aSMatthew G. Knepley           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax);
146975d3a19aSMatthew G. Knepley 
147075d3a19aSMatthew G. Knepley           newSize += 1;
147175d3a19aSMatthew G. Knepley         } else {
147275d3a19aSMatthew G. Knepley           if      (cone[1] == f) r = 1;
147375d3a19aSMatthew G. Knepley           else if (cone[2] == f) r = 2;
147475d3a19aSMatthew G. Knepley           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
147575d3a19aSMatthew G. Knepley           supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r;
147675d3a19aSMatthew G. Knepley 
147775d3a19aSMatthew G. Knepley           newSize += 2;
147875d3a19aSMatthew G. Knepley         }
147975d3a19aSMatthew G. Knepley       }
148075d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
148175d3a19aSMatthew G. Knepley #if 1
148275d3a19aSMatthew 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);
148375d3a19aSMatthew G. Knepley       for (p = 0; p < newSize; ++p) {
148475d3a19aSMatthew 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);
148575d3a19aSMatthew G. Knepley       }
148675d3a19aSMatthew G. Knepley #endif
148775d3a19aSMatthew G. Knepley     }
148875d3a19aSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
148975d3a19aSMatthew G. Knepley     break;
1490b5da9499SMatthew G. Knepley   case 5:
1491b5da9499SMatthew G. Knepley     /* Simplicial 3D */
1492b5da9499SMatthew G. Knepley     /* All cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
1493b5da9499SMatthew G. Knepley     ierr = DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);CHKERRQ(ierr);
1494b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1495b5da9499SMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*8;
1496b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt;
1497b5da9499SMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
1498b5da9499SMatthew G. Knepley 
1499b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1500b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1501b5da9499SMatthew G. Knepley       /* A tetrahedron: {0, a, c, d} */
1502518a8359SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
1503b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1504518a8359SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
1505b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1506518a8359SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
1507b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1508b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
1509b5da9499SMatthew G. Knepley       orntNew[3] = 0;
1510b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1511b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1512b5da9499SMatthew G. Knepley #if 1
1513b5da9499SMatthew 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);
1514b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1515b5da9499SMatthew 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);
1516b5da9499SMatthew G. Knepley       }
1517b5da9499SMatthew G. Knepley #endif
1518b5da9499SMatthew G. Knepley       /* B tetrahedron: {a, 1, b, e} */
1519518a8359SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
1520b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1521518a8359SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
1522b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1523b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
1524b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1525518a8359SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
1526b5da9499SMatthew G. Knepley       orntNew[3] = ornt[3];
1527b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1528b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1529b5da9499SMatthew G. Knepley #if 1
1530b5da9499SMatthew 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);
1531b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1532b5da9499SMatthew 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);
1533b5da9499SMatthew G. Knepley       }
1534b5da9499SMatthew G. Knepley #endif
1535b5da9499SMatthew G. Knepley       /* C tetrahedron: {c, b, 2, f} */
1536518a8359SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
1537b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1538b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
1539b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1540518a8359SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
1541b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1542518a8359SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
1543b5da9499SMatthew G. Knepley       orntNew[3] = ornt[3];
1544b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1545b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1546b5da9499SMatthew G. Knepley #if 1
1547b5da9499SMatthew 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);
1548b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1549b5da9499SMatthew 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);
1550b5da9499SMatthew G. Knepley       }
1551b5da9499SMatthew G. Knepley #endif
1552b5da9499SMatthew G. Knepley       /* D tetrahedron: {d, e, f, 3} */
1553b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
1554b5da9499SMatthew G. Knepley       orntNew[0] = 0;
1555518a8359SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
1556b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1557518a8359SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
1558b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1559518a8359SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
1560b5da9499SMatthew G. Knepley       orntNew[3] = ornt[3];
1561b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
1562b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
1563b5da9499SMatthew G. Knepley #if 1
1564b5da9499SMatthew 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);
1565b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1566b5da9499SMatthew 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);
1567b5da9499SMatthew G. Knepley       }
1568b5da9499SMatthew G. Knepley #endif
1569b5da9499SMatthew G. Knepley       /* A' tetrahedron: {d, a, c, f} */
1570b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
1571b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1572b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
1573b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1574b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + 3;
1575b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -((-(ornt[2]+1)+2)%3+1) : (ornt[2]+2)%3;
1576b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
1577b5da9499SMatthew G. Knepley       orntNew[3] = 0;
1578b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
1579b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
1580b5da9499SMatthew G. Knepley #if 1
1581b5da9499SMatthew 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);
1582b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1583b5da9499SMatthew 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);
1584b5da9499SMatthew G. Knepley       }
1585b5da9499SMatthew G. Knepley #endif
1586b5da9499SMatthew G. Knepley       /* B' tetrahedron: {e, b, a, f} */
1587b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
1588b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1589b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[3] - fStart)*4 + 3;
1590b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -((-(ornt[3]+1)+1)%3+1) : (ornt[3]+1)%3;
1591b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
1592b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1593b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
1594b5da9499SMatthew G. Knepley       orntNew[3] = 0;
1595b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
1596b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
1597b5da9499SMatthew G. Knepley #if 1
1598b5da9499SMatthew 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);
1599b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1600b5da9499SMatthew 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);
1601b5da9499SMatthew G. Knepley       }
1602b5da9499SMatthew G. Knepley #endif
1603b5da9499SMatthew G. Knepley       /* C' tetrahedron: {b, f, c, a} */
1604b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
1605b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1606b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
1607b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1608b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[0] - fStart)*4 + 3;
1609b5da9499SMatthew G. Knepley       orntNew[2] = ornt[0] < 0 ? (-(ornt[0]+1)+1)%3 : -((ornt[0]+1)%3+1);
1610b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
1611b5da9499SMatthew G. Knepley       orntNew[3] = -1;
1612b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
1613b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
1614b5da9499SMatthew G. Knepley #if 1
1615b5da9499SMatthew 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);
1616b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1617b5da9499SMatthew 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);
1618b5da9499SMatthew G. Knepley       }
1619b5da9499SMatthew G. Knepley #endif
1620b5da9499SMatthew G. Knepley       /* D' tetrahedron: {f, e, d, a} */
1621b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
1622b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1623b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
1624b5da9499SMatthew G. Knepley       orntNew[1] = -3;
1625b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
1626b5da9499SMatthew G. Knepley       orntNew[2] = -2;
1627b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[1] - fStart)*4 + 3;
1628b5da9499SMatthew G. Knepley       orntNew[3] = ornt[2];
1629b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
1630b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
1631b5da9499SMatthew G. Knepley #if 1
1632b5da9499SMatthew 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);
1633b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1634b5da9499SMatthew 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);
1635b5da9499SMatthew G. Knepley       }
1636b5da9499SMatthew G. Knepley #endif
1637b5da9499SMatthew G. Knepley     }
1638b5da9499SMatthew G. Knepley     /* Split faces have 3 edges and the same cells as the parent */
1639b5da9499SMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
1640b5da9499SMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
1641b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
1642b5da9499SMatthew G. Knepley       const PetscInt  newp = fStartNew + (f - fStart)*4;
1643b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt, *support;
1644b5da9499SMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3], coneSize, supportSize, s;
1645b5da9499SMatthew G. Knepley 
1646b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1647b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
1648b5da9499SMatthew G. Knepley       /* A triangle */
1649b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
1650b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1651b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
1652b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1653b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
1654b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1655b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1656b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1657b5da9499SMatthew G. Knepley #if 1
1658b5da9499SMatthew 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);
1659b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1660b5da9499SMatthew 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);
1661b5da9499SMatthew G. Knepley       }
1662b5da9499SMatthew G. Knepley #endif
1663b5da9499SMatthew G. Knepley       /* B triangle */
1664b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
1665b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1666b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
1667b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1668b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
1669b5da9499SMatthew G. Knepley       orntNew[2] = -2;
1670b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1671b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1672b5da9499SMatthew G. Knepley #if 1
1673b5da9499SMatthew 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);
1674b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1675b5da9499SMatthew 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);
1676b5da9499SMatthew G. Knepley       }
1677b5da9499SMatthew G. Knepley #endif
1678b5da9499SMatthew G. Knepley       /* C triangle */
1679b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
1680b5da9499SMatthew G. Knepley       orntNew[0] = -2;
1681b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
1682b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1683b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
1684b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1685b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1686b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1687b5da9499SMatthew G. Knepley #if 1
1688b5da9499SMatthew 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);
1689b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1690b5da9499SMatthew 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);
1691b5da9499SMatthew G. Knepley       }
1692b5da9499SMatthew G. Knepley #endif
1693b5da9499SMatthew G. Knepley       /* D triangle */
1694b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
1695b5da9499SMatthew G. Knepley       orntNew[0] = 0;
1696b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
1697b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1698b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
1699b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1700b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
1701b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
1702b5da9499SMatthew G. Knepley #if 1
1703b5da9499SMatthew 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);
1704b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1705b5da9499SMatthew 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);
1706b5da9499SMatthew G. Knepley       }
1707b5da9499SMatthew G. Knepley #endif
1708b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1709b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1710b5da9499SMatthew G. Knepley       for (r = 0; r < 4; ++r) {
1711b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
1712b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1713b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1714b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1715b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
1716b5da9499SMatthew G. Knepley             if (cone[c] == f) break;
1717b5da9499SMatthew G. Knepley           }
1718b5da9499SMatthew 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]));
1719b5da9499SMatthew G. Knepley         }
1720b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp+r, supportRef);CHKERRQ(ierr);
1721b5da9499SMatthew G. Knepley #if 1
1722b5da9499SMatthew 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);
1723b5da9499SMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
1724b5da9499SMatthew 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);
1725b5da9499SMatthew G. Knepley         }
1726b5da9499SMatthew G. Knepley #endif
1727b5da9499SMatthew G. Knepley       }
1728b5da9499SMatthew G. Knepley     }
1729b5da9499SMatthew G. Knepley     /* Interior faces have 3 edges and 2 cells */
1730b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1731b5da9499SMatthew G. Knepley       PetscInt        newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8;
1732b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt;
1733b5da9499SMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
1734b5da9499SMatthew G. Knepley       PetscInt        supportNew[2];
1735b5da9499SMatthew G. Knepley 
1736b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1737b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1738b5da9499SMatthew G. Knepley       /* Face A: {c, a, d} */
1739b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+0)%3 : (ornt[0]+2)%3);
1740b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1741b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+0)%3 : (ornt[1]+2)%3);
1742b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1] < 0 ? -2 : 0;
1743b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+0)%3 : (ornt[2]+2)%3);
1744b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -2 : 0;
1745b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1746b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1747b5da9499SMatthew G. Knepley #if 1
1748b5da9499SMatthew 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);
1749b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1750b5da9499SMatthew 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);
1751b5da9499SMatthew G. Knepley       }
1752b5da9499SMatthew G. Knepley #endif
1753b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0;
1754b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 0+4;
1755b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1756b5da9499SMatthew G. Knepley #if 1
1757b5da9499SMatthew 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);
1758b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1759b5da9499SMatthew 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);
1760b5da9499SMatthew G. Knepley       }
1761b5da9499SMatthew G. Knepley #endif
1762b5da9499SMatthew G. Knepley       ++newp;
1763b5da9499SMatthew G. Knepley       /* Face B: {a, b, e} */
1764b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+2)%3 : (ornt[0]+0)%3);
1765b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1766b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+2)%3 : (ornt[3]+0)%3);
1767b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1768b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+1)%3 : (ornt[1]+1)%3);
1769b5da9499SMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? -2 : 0;
1770b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1771b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1772b5da9499SMatthew G. Knepley #if 1
1773b5da9499SMatthew 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);
1774b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1775b5da9499SMatthew 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);
1776b5da9499SMatthew G. Knepley       }
1777b5da9499SMatthew G. Knepley #endif
1778b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1;
1779b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 1+4;
1780b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1781b5da9499SMatthew G. Knepley #if 1
1782b5da9499SMatthew 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);
1783b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1784b5da9499SMatthew 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);
1785b5da9499SMatthew G. Knepley       }
1786b5da9499SMatthew G. Knepley #endif
1787b5da9499SMatthew G. Knepley       ++newp;
1788b5da9499SMatthew G. Knepley       /* Face C: {c, f, b} */
1789b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+2)%3 : (ornt[2]+0)%3);
1790b5da9499SMatthew G. Knepley       orntNew[0] = ornt[2] < 0 ? -2 : 0;
1791b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+0)%3 : (ornt[3]+2)%3);
1792b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1793b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+1)%3 : (ornt[0]+1)%3);
1794b5da9499SMatthew G. Knepley       orntNew[2] = ornt[0] < 0 ? -2 : 0;
1795b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1796b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1797b5da9499SMatthew G. Knepley #if 1
1798b5da9499SMatthew 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);
1799b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1800b5da9499SMatthew 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);
1801b5da9499SMatthew G. Knepley       }
1802b5da9499SMatthew G. Knepley #endif
1803b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 2;
1804b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
1805b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1806b5da9499SMatthew G. Knepley #if 1
1807b5da9499SMatthew 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);
1808b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1809b5da9499SMatthew 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);
1810b5da9499SMatthew G. Knepley       }
1811b5da9499SMatthew G. Knepley #endif
1812b5da9499SMatthew G. Knepley       ++newp;
1813b5da9499SMatthew G. Knepley       /* Face D: {d, e, f} */
1814b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+2)%3 : (ornt[1]+0)%3);
1815b5da9499SMatthew G. Knepley       orntNew[0] = ornt[1] < 0 ? -2 : 0;
1816b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+1)%3 : (ornt[3]+1)%3);
1817b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1818b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+1)%3 : (ornt[2]+1)%3);
1819b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -2 : 0;
1820b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1821b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1822b5da9499SMatthew G. Knepley #if 1
1823b5da9499SMatthew 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);
1824b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1825b5da9499SMatthew 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);
1826b5da9499SMatthew G. Knepley       }
1827b5da9499SMatthew G. Knepley #endif
1828b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 3;
1829b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
1830b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1831b5da9499SMatthew G. Knepley #if 1
1832b5da9499SMatthew 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);
1833b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1834b5da9499SMatthew 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);
1835b5da9499SMatthew G. Knepley       }
1836b5da9499SMatthew G. Knepley #endif
1837b5da9499SMatthew G. Knepley       ++newp;
1838b5da9499SMatthew G. Knepley       /* Face E: {d, f, a} */
1839b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+1)%3 : (ornt[2]+1)%3);
1840b5da9499SMatthew G. Knepley       orntNew[0] = ornt[2] < 0 ? 0 : -2;
1841b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1842b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1843b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+0)%3 : (ornt[1]+2)%3);
1844b5da9499SMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? -2 : 0;
1845b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1846b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1847b5da9499SMatthew G. Knepley #if 1
1848b5da9499SMatthew 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);
1849b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1850b5da9499SMatthew 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);
1851b5da9499SMatthew G. Knepley       }
1852b5da9499SMatthew G. Knepley #endif
1853b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0+4;
1854b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
1855b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1856b5da9499SMatthew G. Knepley #if 1
1857b5da9499SMatthew 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);
1858b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1859b5da9499SMatthew 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);
1860b5da9499SMatthew G. Knepley       }
1861b5da9499SMatthew G. Knepley #endif
1862b5da9499SMatthew G. Knepley       ++newp;
1863b5da9499SMatthew G. Knepley       /* Face F: {c, a, f} */
1864b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+0)%3 : (ornt[0]+2)%3);
1865b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1866b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1867b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1868b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+2)%3 : (ornt[2]+0)%3);
1869b5da9499SMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? 0 : -2;
1870b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1871b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1872b5da9499SMatthew G. Knepley #if 1
1873b5da9499SMatthew 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);
1874b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1875b5da9499SMatthew 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);
1876b5da9499SMatthew G. Knepley       }
1877b5da9499SMatthew G. Knepley #endif
1878b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0+4;
1879b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
1880b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1881b5da9499SMatthew G. Knepley #if 1
1882b5da9499SMatthew 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);
1883b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1884b5da9499SMatthew 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);
1885b5da9499SMatthew G. Knepley       }
1886b5da9499SMatthew G. Knepley #endif
1887b5da9499SMatthew G. Knepley       ++newp;
1888b5da9499SMatthew G. Knepley       /* Face G: {e, a, f} */
1889b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+1)%3 : (ornt[1]+1)%3);
1890b5da9499SMatthew G. Knepley       orntNew[0] = ornt[1] < 0 ? -2 : 0;
1891b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1892b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1893b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+1)%3 : (ornt[3]+1)%3);
1894b5da9499SMatthew G. Knepley       orntNew[2] = ornt[3] < 0 ? 0 : -2;
1895b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1896b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1897b5da9499SMatthew G. Knepley #if 1
1898b5da9499SMatthew 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);
1899b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1900b5da9499SMatthew 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);
1901b5da9499SMatthew G. Knepley       }
1902b5da9499SMatthew G. Knepley #endif
1903b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1+4;
1904b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
1905b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1906b5da9499SMatthew G. Knepley #if 1
1907b5da9499SMatthew 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);
1908b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1909b5da9499SMatthew 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);
1910b5da9499SMatthew G. Knepley       }
1911b5da9499SMatthew G. Knepley #endif
1912b5da9499SMatthew G. Knepley       ++newp;
1913b5da9499SMatthew G. Knepley       /* Face H: {a, b, f} */
1914b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+2)%3 : (ornt[0]+0)%3);
1915b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1916b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+0)%3 : (ornt[3]+2)%3);
1917b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? 0 : -2;
1918b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1919b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1920b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1921b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1922b5da9499SMatthew G. Knepley #if 1
1923b5da9499SMatthew 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);
1924b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1925b5da9499SMatthew 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);
1926b5da9499SMatthew G. Knepley       }
1927b5da9499SMatthew G. Knepley #endif
1928b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1+4;
1929b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
1930b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1931b5da9499SMatthew G. Knepley #if 1
1932b5da9499SMatthew 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);
1933b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1934b5da9499SMatthew 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);
1935b5da9499SMatthew G. Knepley       }
1936b5da9499SMatthew G. Knepley #endif
1937b5da9499SMatthew G. Knepley       ++newp;
1938b5da9499SMatthew G. Knepley     }
1939b5da9499SMatthew G. Knepley     /* Split Edges have 2 vertices and the same faces as the parent */
1940b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
1941b5da9499SMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
1942b5da9499SMatthew G. Knepley 
1943b5da9499SMatthew G. Knepley       for (r = 0; r < 2; ++r) {
1944b5da9499SMatthew G. Knepley         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
1945b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
1946b5da9499SMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
1947b5da9499SMatthew G. Knepley 
1948b5da9499SMatthew G. Knepley         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
1949b5da9499SMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
1950b5da9499SMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
1951b5da9499SMatthew G. Knepley         coneNew[(r+1)%2] = newv;
1952b5da9499SMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1953b5da9499SMatthew G. Knepley #if 1
1954b5da9499SMatthew 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);
1955b5da9499SMatthew G. Knepley         for (p = 0; p < 2; ++p) {
1956b5da9499SMatthew 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);
1957b5da9499SMatthew G. Knepley         }
1958b5da9499SMatthew G. Knepley #endif
1959b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
1960b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
1961b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
1962b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1963b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1964b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1965b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
1966b5da9499SMatthew G. Knepley             if (cone[c] == e) break;
1967b5da9499SMatthew G. Knepley           }
1968b5da9499SMatthew G. Knepley           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
1969b5da9499SMatthew G. Knepley         }
1970b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1971b5da9499SMatthew G. Knepley #if 1
1972b5da9499SMatthew 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);
1973b5da9499SMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
1974b5da9499SMatthew 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);
1975b5da9499SMatthew G. Knepley         }
1976b5da9499SMatthew G. Knepley #endif
1977b5da9499SMatthew G. Knepley       }
1978b5da9499SMatthew G. Knepley     }
197986f0afeeSMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
1980b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
1981b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt, *support;
1982b5da9499SMatthew G. Knepley       PetscInt        coneSize, supportSize, s;
1983b5da9499SMatthew G. Knepley 
1984b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1985b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1986b5da9499SMatthew G. Knepley       for (r = 0; r < 3; ++r) {
1987b5da9499SMatthew G. Knepley         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
1988b5da9499SMatthew G. Knepley         PetscInt        coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
1989b5da9499SMatthew G. Knepley         PetscInt        fint[24] = { 1,  7, -1, -1,  0,  5,
1990b5da9499SMatthew G. Knepley                                     -1, -1,  1,  6,  0,  4,
1991b5da9499SMatthew G. Knepley                                      2,  5,  3,  4, -1, -1,
1992b5da9499SMatthew G. Knepley                                     -1, -1,  3,  6,  2,  7};
1993b5da9499SMatthew G. Knepley 
1994b5da9499SMatthew G. Knepley         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1995b5da9499SMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
1996b5da9499SMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
1997b5da9499SMatthew G. Knepley         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1998b5da9499SMatthew G. Knepley #if 1
1999b5da9499SMatthew 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);
2000b5da9499SMatthew G. Knepley         for (p = 0; p < 2; ++p) {
2001b5da9499SMatthew 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);
2002b5da9499SMatthew G. Knepley         }
2003b5da9499SMatthew G. Knepley #endif
2004b5da9499SMatthew G. Knepley         supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
2005b5da9499SMatthew G. Knepley         supportRef[1] = fStartNew + (f - fStart)*4 + 3;
2006b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
2007b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2008b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2009b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
2010b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
201186f0afeeSMatthew G. Knepley           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
201286f0afeeSMatthew G. Knepley           er   = ornt[c] < 0 ? (-(ornt[c]+1) + 2-r)%3 : (ornt[c] + r)%3;
2013b5da9499SMatthew G. Knepley           if (er == eint[c]) {
2014b5da9499SMatthew G. Knepley             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
2015b5da9499SMatthew G. Knepley           } else {
2016b5da9499SMatthew G. Knepley             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
2017b5da9499SMatthew G. Knepley             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
2018b5da9499SMatthew G. Knepley           }
2019b5da9499SMatthew G. Knepley         }
2020b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2021b5da9499SMatthew G. Knepley #if 1
2022b5da9499SMatthew 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);
2023b5da9499SMatthew G. Knepley         for (p = 0; p < intFaces; ++p) {
2024b5da9499SMatthew 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);
2025b5da9499SMatthew G. Knepley         }
2026b5da9499SMatthew G. Knepley #endif
2027b5da9499SMatthew G. Knepley       }
2028b5da9499SMatthew G. Knepley     }
2029b5da9499SMatthew G. Knepley     /* Interior edges have 2 vertices and 4 faces */
2030b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
2031b5da9499SMatthew G. Knepley       const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2032b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt, *fcone;
20334a40f731SMatthew G. Knepley       PetscInt        coneNew[2], supportNew[4], find;
2034b5da9499SMatthew G. Knepley 
2035b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2036b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2037b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, cone[0], &fcone);CHKERRQ(ierr);
203842525629SMatthew G. Knepley       find = GetTriEdge_Static(ornt[0], 0);
2039b5da9499SMatthew G. Knepley       coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
2040b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, cone[2], &fcone);CHKERRQ(ierr);
204142525629SMatthew G. Knepley       find = GetTriEdge_Static(ornt[2], 1);
2042b5da9499SMatthew G. Knepley       coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
2043b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2044b5da9499SMatthew G. Knepley #if 1
2045b5da9499SMatthew 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);
2046b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
2047b5da9499SMatthew 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);
2048b5da9499SMatthew G. Knepley       }
2049b5da9499SMatthew G. Knepley #endif
2050b5da9499SMatthew G. Knepley       supportNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
2051b5da9499SMatthew G. Knepley       supportNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
2052b5da9499SMatthew G. Knepley       supportNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
2053b5da9499SMatthew G. Knepley       supportNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
2054b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2055b5da9499SMatthew G. Knepley #if 1
2056b5da9499SMatthew 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);
2057b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
2058b5da9499SMatthew 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);
2059b5da9499SMatthew G. Knepley       }
2060b5da9499SMatthew G. Knepley #endif
2061b5da9499SMatthew G. Knepley     }
2062b5da9499SMatthew G. Knepley     /* Old vertices have identical supports */
2063b5da9499SMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
2064b5da9499SMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
2065b5da9499SMatthew G. Knepley       const PetscInt *support, *cone;
2066b5da9499SMatthew G. Knepley       PetscInt        size, s;
2067b5da9499SMatthew G. Knepley 
2068b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
2069b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
2070b5da9499SMatthew G. Knepley       for (s = 0; s < size; ++s) {
2071b5da9499SMatthew G. Knepley         PetscInt r = 0;
2072b5da9499SMatthew G. Knepley 
2073b5da9499SMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2074b5da9499SMatthew G. Knepley         if (cone[1] == v) r = 1;
2075b5da9499SMatthew G. Knepley         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
2076b5da9499SMatthew G. Knepley       }
2077b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2078b5da9499SMatthew G. Knepley #if 1
2079b5da9499SMatthew 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);
2080b5da9499SMatthew G. Knepley       for (p = 0; p < size; ++p) {
2081b5da9499SMatthew 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);
2082b5da9499SMatthew G. Knepley       }
2083b5da9499SMatthew G. Knepley #endif
2084b5da9499SMatthew G. Knepley     }
2085b5da9499SMatthew G. Knepley     /* Edge vertices have 2 + face*2 + 0/1 supports */
2086b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
2087b5da9499SMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
2088b5da9499SMatthew G. Knepley       const PetscInt *cone, *support;
2089b5da9499SMatthew G. Knepley       PetscInt       *star = NULL, starSize, cellSize = 0, coneSize, size, s;
2090b5da9499SMatthew G. Knepley 
2091b5da9499SMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
2092b5da9499SMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
2093b5da9499SMatthew G. Knepley       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
2094b5da9499SMatthew G. Knepley       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
2095b5da9499SMatthew G. Knepley       for (s = 0; s < size; ++s) {
2096b5da9499SMatthew G. Knepley         PetscInt r = 0;
2097b5da9499SMatthew G. Knepley 
2098b5da9499SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2099b5da9499SMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2100b5da9499SMatthew G. Knepley         for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
2101b5da9499SMatthew G. Knepley         supportRef[2+s*2+0] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
2102b5da9499SMatthew G. Knepley         supportRef[2+s*2+1] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
2103b5da9499SMatthew G. Knepley       }
2104b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
2105b5da9499SMatthew G. Knepley       for (s = 0; s < starSize*2; s += 2) {
2106b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt;
2107b5da9499SMatthew G. Knepley         PetscInt        e01, e23;
2108b5da9499SMatthew G. Knepley 
2109b5da9499SMatthew G. Knepley         if ((star[s] >= cStart) && (star[s] < cEnd)) {
2110b5da9499SMatthew G. Knepley           /* Check edge 0-1 */
2111b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
2112b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
2113b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
211442525629SMatthew G. Knepley           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
2115b5da9499SMatthew G. Knepley           /* Check edge 2-3 */
2116b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
2117b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
211842525629SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
211942525629SMatthew G. Knepley           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
2120b5da9499SMatthew G. Knepley           if ((e01 == e) || (e23 == e)) {supportRef[2+size*2+cellSize++] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (star[s] - cStart);}
2121b5da9499SMatthew G. Knepley         }
2122b5da9499SMatthew G. Knepley       }
2123b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
2124b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2125b5da9499SMatthew G. Knepley #if 1
2126b5da9499SMatthew 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);
2127b5da9499SMatthew G. Knepley       for (p = 0; p < 2+size*2+cellSize; ++p) {
2128b5da9499SMatthew 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);
2129b5da9499SMatthew G. Knepley       }
2130b5da9499SMatthew G. Knepley #endif
2131b5da9499SMatthew G. Knepley     }
2132b5da9499SMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
2133b5da9499SMatthew G. Knepley     ierr = DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);CHKERRQ(ierr);
2134b5da9499SMatthew G. Knepley     break;
21356ce3c06aSMatthew G. Knepley   case 7:
21366ce3c06aSMatthew G. Knepley     /* Hybrid Simplicial 3D */
21376ce3c06aSMatthew G. Knepley     ierr = DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);CHKERRQ(ierr);
21386ce3c06aSMatthew G. Knepley     /* Interior cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
21396ce3c06aSMatthew G. Knepley     ierr = DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);CHKERRQ(ierr);
21406ce3c06aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
21416ce3c06aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*8;
21426ce3c06aSMatthew G. Knepley       const PetscInt *cone, *ornt;
21436ce3c06aSMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
21446ce3c06aSMatthew G. Knepley 
21456ce3c06aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
21466ce3c06aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
21476ce3c06aSMatthew G. Knepley       /* A tetrahedron: {0, a, c, d} */
21486ce3c06aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
21496ce3c06aSMatthew G. Knepley       orntNew[0] = ornt[0];
21506ce3c06aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
21516ce3c06aSMatthew G. Knepley       orntNew[1] = ornt[1];
21526ce3c06aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
21536ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[2];
21546ce3c06aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 0;
21556ce3c06aSMatthew G. Knepley       orntNew[3] = 0;
21566ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
21576ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
21586ce3c06aSMatthew G. Knepley #if 1
21596ce3c06aSMatthew G. Knepley       if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cMaxNew);
21606ce3c06aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
21616ce3c06aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
21626ce3c06aSMatthew G. Knepley       }
21636ce3c06aSMatthew G. Knepley #endif
21646ce3c06aSMatthew G. Knepley       /* B tetrahedron: {a, 1, b, e} */
21656ce3c06aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
21666ce3c06aSMatthew G. Knepley       orntNew[0] = ornt[0];
21676ce3c06aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
21686ce3c06aSMatthew G. Knepley       orntNew[1] = ornt[1];
21696ce3c06aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 1;
21706ce3c06aSMatthew G. Knepley       orntNew[2] = 0;
21716ce3c06aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
21726ce3c06aSMatthew G. Knepley       orntNew[3] = ornt[3];
21736ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
21746ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
21756ce3c06aSMatthew G. Knepley #if 1
21766ce3c06aSMatthew G. Knepley       if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cMaxNew);
21776ce3c06aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
21786ce3c06aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
21796ce3c06aSMatthew G. Knepley       }
21806ce3c06aSMatthew G. Knepley #endif
21816ce3c06aSMatthew G. Knepley       /* C tetrahedron: {c, b, 2, f} */
21826ce3c06aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
21836ce3c06aSMatthew G. Knepley       orntNew[0] = ornt[0];
21846ce3c06aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 2;
21856ce3c06aSMatthew G. Knepley       orntNew[1] = 0;
21866ce3c06aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
21876ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[2];
21886ce3c06aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
21896ce3c06aSMatthew G. Knepley       orntNew[3] = ornt[3];
21906ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
21916ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
21926ce3c06aSMatthew G. Knepley #if 1
21936ce3c06aSMatthew G. Knepley       if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cMaxNew);
21946ce3c06aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
21956ce3c06aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
21966ce3c06aSMatthew G. Knepley       }
21976ce3c06aSMatthew G. Knepley #endif
21986ce3c06aSMatthew G. Knepley       /* D tetrahedron: {d, e, f, 3} */
21996ce3c06aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 3;
22006ce3c06aSMatthew G. Knepley       orntNew[0] = 0;
22016ce3c06aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
22026ce3c06aSMatthew G. Knepley       orntNew[1] = ornt[1];
22036ce3c06aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
22046ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[2];
22056ce3c06aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
22066ce3c06aSMatthew G. Knepley       orntNew[3] = ornt[3];
22076ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
22086ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
22096ce3c06aSMatthew G. Knepley #if 1
22106ce3c06aSMatthew G. Knepley       if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cMaxNew);
22116ce3c06aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
22126ce3c06aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
22136ce3c06aSMatthew G. Knepley       }
22146ce3c06aSMatthew G. Knepley #endif
22156ce3c06aSMatthew G. Knepley       /* A' tetrahedron: {d, a, c, f} */
22166ce3c06aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 0;
22176ce3c06aSMatthew G. Knepley       orntNew[0] = -3;
22186ce3c06aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 4;
22196ce3c06aSMatthew G. Knepley       orntNew[1] = 0;
22206ce3c06aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + 3;
22216ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -((-(ornt[2]+1)+2)%3+1) : (ornt[2]+2)%3;
22226ce3c06aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 5;
22236ce3c06aSMatthew G. Knepley       orntNew[3] = 0;
22246ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
22256ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
22266ce3c06aSMatthew G. Knepley #if 1
22276ce3c06aSMatthew G. Knepley       if ((newp+4 < cStartNew) || (newp+4 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+4, cStartNew, cMaxNew);
22286ce3c06aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
22296ce3c06aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
22306ce3c06aSMatthew G. Knepley       }
22316ce3c06aSMatthew G. Knepley #endif
22326ce3c06aSMatthew G. Knepley       /* B' tetrahedron: {e, b, a, f} */
22336ce3c06aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 1;
22346ce3c06aSMatthew G. Knepley       orntNew[0] = -3;
22356ce3c06aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[3] - fStart)*4 + 3;
22366ce3c06aSMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -((-(ornt[3]+1)+1)%3+1) : (ornt[3]+1)%3;
22376ce3c06aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 6;
22386ce3c06aSMatthew G. Knepley       orntNew[2] = 0;
22396ce3c06aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 7;
22406ce3c06aSMatthew G. Knepley       orntNew[3] = 0;
22416ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
22426ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
22436ce3c06aSMatthew G. Knepley #if 1
22446ce3c06aSMatthew G. Knepley       if ((newp+5 < cStartNew) || (newp+5 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+5, cStartNew, cMaxNew);
22456ce3c06aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
22466ce3c06aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
22476ce3c06aSMatthew G. Knepley       }
22486ce3c06aSMatthew G. Knepley #endif
22496ce3c06aSMatthew G. Knepley       /* C' tetrahedron: {b, f, c, a} */
22506ce3c06aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 2;
22516ce3c06aSMatthew G. Knepley       orntNew[0] = -3;
22526ce3c06aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 7;
22536ce3c06aSMatthew G. Knepley       orntNew[1] = -2;
22546ce3c06aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[0] - fStart)*4 + 3;
22556ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[0] < 0 ? (-(ornt[0]+1)+1)%3 : -((ornt[0]+1)%3+1);
22566ce3c06aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 5;
22576ce3c06aSMatthew G. Knepley       orntNew[3] = -1;
22586ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
22596ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
22606ce3c06aSMatthew G. Knepley #if 1
22616ce3c06aSMatthew G. Knepley       if ((newp+6 < cStartNew) || (newp+6 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+6, cStartNew, cMaxNew);
22626ce3c06aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
22636ce3c06aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
22646ce3c06aSMatthew G. Knepley       }
22656ce3c06aSMatthew G. Knepley #endif
22666ce3c06aSMatthew G. Knepley       /* D' tetrahedron: {f, e, d, a} */
22676ce3c06aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 3;
22686ce3c06aSMatthew G. Knepley       orntNew[0] = -3;
22696ce3c06aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 6;
22706ce3c06aSMatthew G. Knepley       orntNew[1] = -3;
22716ce3c06aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 4;
22726ce3c06aSMatthew G. Knepley       orntNew[2] = -2;
22736ce3c06aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[1] - fStart)*4 + 3;
22746ce3c06aSMatthew G. Knepley       orntNew[3] = ornt[2];
22756ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
22766ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
22776ce3c06aSMatthew G. Knepley #if 1
22786ce3c06aSMatthew G. Knepley       if ((newp+7 < cStartNew) || (newp+7 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+7, cStartNew, cMaxNew);
22796ce3c06aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
22806ce3c06aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
22816ce3c06aSMatthew G. Knepley       }
22826ce3c06aSMatthew G. Knepley #endif
22836ce3c06aSMatthew G. Knepley     }
22846ce3c06aSMatthew G. Knepley     /* Hybrid cells have 5 faces */
22856ce3c06aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
22866ce3c06aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4;
2287d3a1cc75SMatthew G. Knepley       const PetscInt *cone, *ornt, *fornt;
22886ce3c06aSMatthew G. Knepley       PetscInt        coneNew[5], orntNew[5];
22896ce3c06aSMatthew G. Knepley 
22906ce3c06aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
22916ce3c06aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2292d3a1cc75SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, cone[0], &fornt);CHKERRQ(ierr);
22936ce3c06aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
22946ce3c06aSMatthew G. Knepley         coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], r);
22956ce3c06aSMatthew G. Knepley         orntNew[0] = ornt[0];
22966ce3c06aSMatthew G. Knepley         coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], r);
22976ce3c06aSMatthew G. Knepley         orntNew[1] = ornt[1];
2298d3a1cc75SMatthew G. Knepley         coneNew[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], (r+2)%3)] - fMax)*2 + (fornt[GetTriEdge_Static(ornt[0], (r+2)%3)] < 0 ? 0 : 1);
22996ce3c06aSMatthew G. Knepley         orntNew[2] = 0;
2300d3a1cc75SMatthew G. Knepley         coneNew[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], r)]       - fMax)*2 + (fornt[GetTriEdge_Static(ornt[0], r)]       < 0 ? 1 : 0);
23016ce3c06aSMatthew G. Knepley         orntNew[3] = 0;
23026ce3c06aSMatthew G. Knepley         coneNew[4] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + GetTriSubface_Static(ornt[0], r);
23036ce3c06aSMatthew G. Knepley         orntNew[4] = 0;
23046ce3c06aSMatthew G. Knepley         ierr = DMPlexSetCone(rdm, newp+r, coneNew);CHKERRQ(ierr);
23056ce3c06aSMatthew G. Knepley         ierr = DMPlexSetConeOrientation(rdm, newp+r, orntNew);CHKERRQ(ierr);
23066ce3c06aSMatthew G. Knepley #if 1
23076ce3c06aSMatthew G. Knepley         if ((newp+r < cMaxNew) || (newp+r >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", newp+r, cMaxNew, cEndNew);
23086ce3c06aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
23096ce3c06aSMatthew G. Knepley           if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
23106ce3c06aSMatthew G. Knepley         }
23116ce3c06aSMatthew G. Knepley         for (p = 2; p < 5; ++p) {
23126ce3c06aSMatthew G. Knepley           if ((coneNew[p] < fMaxNew)   || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", coneNew[p], fMaxNew, fEndNew);
23136ce3c06aSMatthew G. Knepley         }
23146ce3c06aSMatthew G. Knepley #endif
23156ce3c06aSMatthew G. Knepley       }
23166ce3c06aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + 3;
23176ce3c06aSMatthew G. Knepley       orntNew[0] = 0;
23186ce3c06aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + 3;
23196ce3c06aSMatthew G. Knepley       orntNew[1] = 0;
23206ce3c06aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;
23216ce3c06aSMatthew G. Knepley       orntNew[2] = 0;
23226ce3c06aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;
23236ce3c06aSMatthew G. Knepley       orntNew[3] = 0;
23246ce3c06aSMatthew G. Knepley       coneNew[4] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;
23256ce3c06aSMatthew G. Knepley       orntNew[4] = 0;
23266ce3c06aSMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
23276ce3c06aSMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
23286ce3c06aSMatthew G. Knepley #if 1
23296ce3c06aSMatthew G. Knepley       if ((newp+3 < cMaxNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", newp+3, cMaxNew, cEndNew);
23306ce3c06aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
23316ce3c06aSMatthew G. Knepley         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
23326ce3c06aSMatthew G. Knepley       }
23336ce3c06aSMatthew G. Knepley       for (p = 2; p < 5; ++p) {
23346ce3c06aSMatthew G. Knepley         if ((coneNew[p] < fMaxNew)   || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", coneNew[p], fMaxNew, fEndNew);
23356ce3c06aSMatthew G. Knepley       }
23366ce3c06aSMatthew G. Knepley #endif
23376ce3c06aSMatthew G. Knepley     }
23386ce3c06aSMatthew G. Knepley     /* Split faces have 3 edges and the same cells as the parent */
23396ce3c06aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
23406ce3c06aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
23416ce3c06aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
23426ce3c06aSMatthew G. Knepley       const PetscInt  newp = fStartNew + (f - fStart)*4;
23436ce3c06aSMatthew G. Knepley       const PetscInt *cone, *ornt, *support;
23446ce3c06aSMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3], coneSize, supportSize, s;
23456ce3c06aSMatthew G. Knepley 
23466ce3c06aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
23476ce3c06aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
23486ce3c06aSMatthew G. Knepley       /* A triangle */
23496ce3c06aSMatthew G. Knepley       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
23506ce3c06aSMatthew G. Knepley       orntNew[0] = ornt[0];
23516ce3c06aSMatthew G. Knepley       coneNew[1] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
23526ce3c06aSMatthew G. Knepley       orntNew[1] = -2;
23536ce3c06aSMatthew G. Knepley       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
23546ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[2];
23556ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
23566ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
23576ce3c06aSMatthew G. Knepley #if 1
23586ce3c06aSMatthew G. Knepley       if ((newp+0 < fStartNew) || (newp+0 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+0, fStartNew, fMaxNew);
23596ce3c06aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
23606ce3c06aSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
23616ce3c06aSMatthew G. Knepley       }
23626ce3c06aSMatthew G. Knepley #endif
23636ce3c06aSMatthew G. Knepley       /* B triangle */
23646ce3c06aSMatthew G. Knepley       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
23656ce3c06aSMatthew G. Knepley       orntNew[0] = ornt[0];
23666ce3c06aSMatthew G. Knepley       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
23676ce3c06aSMatthew G. Knepley       orntNew[1] = ornt[1];
23686ce3c06aSMatthew G. Knepley       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
23696ce3c06aSMatthew G. Knepley       orntNew[2] = -2;
23706ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
23716ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
23726ce3c06aSMatthew G. Knepley #if 1
23736ce3c06aSMatthew G. Knepley       if ((newp+1 < fStartNew) || (newp+1 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+1, fStartNew, fMaxNew);
23746ce3c06aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
23756ce3c06aSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
23766ce3c06aSMatthew G. Knepley       }
23776ce3c06aSMatthew G. Knepley #endif
23786ce3c06aSMatthew G. Knepley       /* C triangle */
23796ce3c06aSMatthew G. Knepley       coneNew[0] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
23806ce3c06aSMatthew G. Knepley       orntNew[0] = -2;
23816ce3c06aSMatthew G. Knepley       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
23826ce3c06aSMatthew G. Knepley       orntNew[1] = ornt[1];
23836ce3c06aSMatthew G. Knepley       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
23846ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[2];
23856ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
23866ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
23876ce3c06aSMatthew G. Knepley #if 1
23886ce3c06aSMatthew G. Knepley       if ((newp+2 < fStartNew) || (newp+2 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+2, fStartNew, fMaxNew);
23896ce3c06aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
23906ce3c06aSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
23916ce3c06aSMatthew G. Knepley       }
23926ce3c06aSMatthew G. Knepley #endif
23936ce3c06aSMatthew G. Knepley       /* D triangle */
23946ce3c06aSMatthew G. Knepley       coneNew[0] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
23956ce3c06aSMatthew G. Knepley       orntNew[0] = 0;
23966ce3c06aSMatthew G. Knepley       coneNew[1] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
23976ce3c06aSMatthew G. Knepley       orntNew[1] = 0;
23986ce3c06aSMatthew G. Knepley       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
23996ce3c06aSMatthew G. Knepley       orntNew[2] = 0;
24006ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
24016ce3c06aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
24026ce3c06aSMatthew G. Knepley #if 1
24036ce3c06aSMatthew G. Knepley       if ((newp+3 < fStartNew) || (newp+3 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+3, fStartNew, fMaxNew);
24046ce3c06aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
24056ce3c06aSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
24066ce3c06aSMatthew G. Knepley       }
24076ce3c06aSMatthew G. Knepley #endif
24086ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
24096ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
24106ce3c06aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
24116ce3c06aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
24126ce3c06aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
24136ce3c06aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
24146ce3c06aSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
24156ce3c06aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
24166ce3c06aSMatthew G. Knepley             if (cone[c] == f) break;
24176ce3c06aSMatthew G. Knepley           }
24186ce3c06aSMatthew G. Knepley           if (support[s] < cMax) {
24196ce3c06aSMatthew 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]));
24206ce3c06aSMatthew G. Knepley           } else {
2421d3a1cc75SMatthew G. Knepley             supportRef[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (r==3 ? r : GetTriSubfaceInverse_Static(ornt[c], r));
24226ce3c06aSMatthew G. Knepley           }
24236ce3c06aSMatthew G. Knepley         }
24246ce3c06aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp+r, supportRef);CHKERRQ(ierr);
24256ce3c06aSMatthew G. Knepley #if 1
24266ce3c06aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
24276ce3c06aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
24286ce3c06aSMatthew G. Knepley           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
24296ce3c06aSMatthew G. Knepley         }
24306ce3c06aSMatthew G. Knepley #endif
24316ce3c06aSMatthew G. Knepley       }
24326ce3c06aSMatthew G. Knepley     }
24336ce3c06aSMatthew G. Knepley     /* Interior cell faces have 3 edges and 2 cells */
24346ce3c06aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
24356ce3c06aSMatthew G. Knepley       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8;
24366ce3c06aSMatthew G. Knepley       const PetscInt *cone, *ornt;
24376ce3c06aSMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
24386ce3c06aSMatthew G. Knepley       PetscInt        supportNew[2];
24396ce3c06aSMatthew G. Knepley 
24406ce3c06aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
24416ce3c06aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
24426ce3c06aSMatthew G. Knepley       /* Face A: {c, a, d} */
24436ce3c06aSMatthew G. Knepley       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+0)%3 : (ornt[0]+2)%3);
24446ce3c06aSMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
24456ce3c06aSMatthew G. Knepley       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+0)%3 : (ornt[1]+2)%3);
24466ce3c06aSMatthew G. Knepley       orntNew[1] = ornt[1] < 0 ? -2 : 0;
24476ce3c06aSMatthew G. Knepley       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+0)%3 : (ornt[2]+2)%3);
24486ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -2 : 0;
24496ce3c06aSMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
24506ce3c06aSMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
24516ce3c06aSMatthew G. Knepley #if 1
24526ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
24536ce3c06aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
24546ce3c06aSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
24556ce3c06aSMatthew G. Knepley       }
24566ce3c06aSMatthew G. Knepley #endif
24576ce3c06aSMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0;
24586ce3c06aSMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 0+4;
24596ce3c06aSMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
24606ce3c06aSMatthew G. Knepley #if 1
24616ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
24626ce3c06aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
24636ce3c06aSMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
24646ce3c06aSMatthew G. Knepley       }
24656ce3c06aSMatthew G. Knepley #endif
24666ce3c06aSMatthew G. Knepley       ++newp;
24676ce3c06aSMatthew G. Knepley       /* Face B: {a, b, e} */
24686ce3c06aSMatthew G. Knepley       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+2)%3 : (ornt[0]+0)%3);
24696ce3c06aSMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
24706ce3c06aSMatthew G. Knepley       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+2)%3 : (ornt[3]+0)%3);
24716ce3c06aSMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
24726ce3c06aSMatthew G. Knepley       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+1)%3 : (ornt[1]+1)%3);
24736ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? -2 : 0;
24746ce3c06aSMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
24756ce3c06aSMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
24766ce3c06aSMatthew G. Knepley #if 1
24776ce3c06aSMatthew G. Knepley       if ((newp+1 < fStartNew) || (newp+1 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+1, fStartNew, fMaxNew);
24786ce3c06aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
24796ce3c06aSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
24806ce3c06aSMatthew G. Knepley       }
24816ce3c06aSMatthew G. Knepley #endif
24826ce3c06aSMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1;
24836ce3c06aSMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 1+4;
24846ce3c06aSMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
24856ce3c06aSMatthew G. Knepley #if 1
24866ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
24876ce3c06aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
24886ce3c06aSMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
24896ce3c06aSMatthew G. Knepley       }
24906ce3c06aSMatthew G. Knepley #endif
24916ce3c06aSMatthew G. Knepley       ++newp;
24926ce3c06aSMatthew G. Knepley       /* Face C: {c, f, b} */
24936ce3c06aSMatthew G. Knepley       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+2)%3 : (ornt[2]+0)%3);
24946ce3c06aSMatthew G. Knepley       orntNew[0] = ornt[2] < 0 ? -2 : 0;
24956ce3c06aSMatthew G. Knepley       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+0)%3 : (ornt[3]+2)%3);
24966ce3c06aSMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
24976ce3c06aSMatthew G. Knepley       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+1)%3 : (ornt[0]+1)%3);
24986ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[0] < 0 ? -2 : 0;
24996ce3c06aSMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
25006ce3c06aSMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
25016ce3c06aSMatthew G. Knepley #if 1
25026ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
25036ce3c06aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
25046ce3c06aSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
25056ce3c06aSMatthew G. Knepley       }
25066ce3c06aSMatthew G. Knepley #endif
25076ce3c06aSMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 2;
25086ce3c06aSMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
25096ce3c06aSMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
25106ce3c06aSMatthew G. Knepley #if 1
25116ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
25126ce3c06aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
25136ce3c06aSMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
25146ce3c06aSMatthew G. Knepley       }
25156ce3c06aSMatthew G. Knepley #endif
25166ce3c06aSMatthew G. Knepley       ++newp;
25176ce3c06aSMatthew G. Knepley       /* Face D: {d, e, f} */
25186ce3c06aSMatthew G. Knepley       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+2)%3 : (ornt[1]+0)%3);
25196ce3c06aSMatthew G. Knepley       orntNew[0] = ornt[1] < 0 ? -2 : 0;
25206ce3c06aSMatthew G. Knepley       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+1)%3 : (ornt[3]+1)%3);
25216ce3c06aSMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
25226ce3c06aSMatthew G. Knepley       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+1)%3 : (ornt[2]+1)%3);
25236ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -2 : 0;
25246ce3c06aSMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
25256ce3c06aSMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
25266ce3c06aSMatthew G. Knepley #if 1
25276ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
25286ce3c06aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
25296ce3c06aSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
25306ce3c06aSMatthew G. Knepley       }
25316ce3c06aSMatthew G. Knepley #endif
25326ce3c06aSMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 3;
25336ce3c06aSMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
25346ce3c06aSMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
25356ce3c06aSMatthew G. Knepley #if 1
25366ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
25376ce3c06aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
25386ce3c06aSMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
25396ce3c06aSMatthew G. Knepley       }
25406ce3c06aSMatthew G. Knepley #endif
25416ce3c06aSMatthew G. Knepley       ++newp;
25426ce3c06aSMatthew G. Knepley       /* Face E: {d, f, a} */
25436ce3c06aSMatthew G. Knepley       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+1)%3 : (ornt[2]+1)%3);
25446ce3c06aSMatthew G. Knepley       orntNew[0] = ornt[2] < 0 ? 0 : -2;
25456ce3c06aSMatthew G. Knepley       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
25466ce3c06aSMatthew G. Knepley       orntNew[1] = 0;
25476ce3c06aSMatthew G. Knepley       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+0)%3 : (ornt[1]+2)%3);
25486ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? -2 : 0;
25496ce3c06aSMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
25506ce3c06aSMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
25516ce3c06aSMatthew G. Knepley #if 1
25526ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
25536ce3c06aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
25546ce3c06aSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
25556ce3c06aSMatthew G. Knepley       }
25566ce3c06aSMatthew G. Knepley #endif
25576ce3c06aSMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0+4;
25586ce3c06aSMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
25596ce3c06aSMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
25606ce3c06aSMatthew G. Knepley #if 1
25616ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
25626ce3c06aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
25636ce3c06aSMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
25646ce3c06aSMatthew G. Knepley       }
25656ce3c06aSMatthew G. Knepley #endif
25666ce3c06aSMatthew G. Knepley       ++newp;
25676ce3c06aSMatthew G. Knepley       /* Face F: {c, a, f} */
25686ce3c06aSMatthew G. Knepley       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+0)%3 : (ornt[0]+2)%3);
25696ce3c06aSMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
25706ce3c06aSMatthew G. Knepley       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
25716ce3c06aSMatthew G. Knepley       orntNew[1] = -2;
25726ce3c06aSMatthew G. Knepley       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+2)%3 : (ornt[2]+0)%3);
25736ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? 0 : -2;
25746ce3c06aSMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
25756ce3c06aSMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
25766ce3c06aSMatthew G. Knepley #if 1
25776ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
25786ce3c06aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
25796ce3c06aSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
25806ce3c06aSMatthew G. Knepley       }
25816ce3c06aSMatthew G. Knepley #endif
25826ce3c06aSMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0+4;
25836ce3c06aSMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
25846ce3c06aSMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
25856ce3c06aSMatthew G. Knepley #if 1
25866ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
25876ce3c06aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
25886ce3c06aSMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
25896ce3c06aSMatthew G. Knepley       }
25906ce3c06aSMatthew G. Knepley #endif
25916ce3c06aSMatthew G. Knepley       ++newp;
25926ce3c06aSMatthew G. Knepley       /* Face G: {e, a, f} */
25936ce3c06aSMatthew G. Knepley       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+1)%3 : (ornt[1]+1)%3);
25946ce3c06aSMatthew G. Knepley       orntNew[0] = ornt[1] < 0 ? -2 : 0;
25956ce3c06aSMatthew G. Knepley       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
25966ce3c06aSMatthew G. Knepley       orntNew[1] = -2;
25976ce3c06aSMatthew G. Knepley       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+1)%3 : (ornt[3]+1)%3);
25986ce3c06aSMatthew G. Knepley       orntNew[2] = ornt[3] < 0 ? 0 : -2;
25996ce3c06aSMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
26006ce3c06aSMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
26016ce3c06aSMatthew G. Knepley #if 1
26026ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
26036ce3c06aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
26046ce3c06aSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
26056ce3c06aSMatthew G. Knepley       }
26066ce3c06aSMatthew G. Knepley #endif
26076ce3c06aSMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1+4;
26086ce3c06aSMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
26096ce3c06aSMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
26106ce3c06aSMatthew G. Knepley #if 1
26116ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
26126ce3c06aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
26136ce3c06aSMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
26146ce3c06aSMatthew G. Knepley       }
26156ce3c06aSMatthew G. Knepley #endif
26166ce3c06aSMatthew G. Knepley       ++newp;
26176ce3c06aSMatthew G. Knepley       /* Face H: {a, b, f} */
26186ce3c06aSMatthew G. Knepley       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+2)%3 : (ornt[0]+0)%3);
26196ce3c06aSMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
26206ce3c06aSMatthew G. Knepley       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+0)%3 : (ornt[3]+2)%3);
26216ce3c06aSMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? 0 : -2;
26226ce3c06aSMatthew G. Knepley       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
26236ce3c06aSMatthew G. Knepley       orntNew[2] = 0;
26246ce3c06aSMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
26256ce3c06aSMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
26266ce3c06aSMatthew G. Knepley #if 1
26276ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
26286ce3c06aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
26296ce3c06aSMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
26306ce3c06aSMatthew G. Knepley       }
26316ce3c06aSMatthew G. Knepley #endif
26326ce3c06aSMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1+4;
26336ce3c06aSMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
26346ce3c06aSMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
26356ce3c06aSMatthew G. Knepley #if 1
26366ce3c06aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
26376ce3c06aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
26386ce3c06aSMatthew G. Knepley         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
26396ce3c06aSMatthew G. Knepley       }
26406ce3c06aSMatthew G. Knepley #endif
26416ce3c06aSMatthew G. Knepley       ++newp;
26426ce3c06aSMatthew G. Knepley     }
26436ce3c06aSMatthew G. Knepley     /* Hybrid split faces have 4 edges and same cells */
26446ce3c06aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
26456ce3c06aSMatthew G. Knepley       const PetscInt *cone, *ornt, *support;
26466ce3c06aSMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
26476ce3c06aSMatthew G. Knepley       PetscInt        supportNew[2], size, s, c;
26486ce3c06aSMatthew G. Knepley 
26496ce3c06aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
26506ce3c06aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
26516ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
26526ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
26536ce3c06aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
26546ce3c06aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;
26556ce3c06aSMatthew G. Knepley 
26566ce3c06aSMatthew G. Knepley         coneNew[0]   = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
26576ce3c06aSMatthew G. Knepley         orntNew[0]   = ornt[0];
26586ce3c06aSMatthew G. Knepley         coneNew[1]   = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
26596ce3c06aSMatthew G. Knepley         orntNew[1]   = ornt[1];
26606ce3c06aSMatthew G. Knepley         coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (cone[2+r] - eMax);
26616ce3c06aSMatthew G. Knepley         orntNew[2+r] = 0;
26626ce3c06aSMatthew G. Knepley         coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd      - eMax) + (f - fMax);
26636ce3c06aSMatthew G. Knepley         orntNew[3-r] = 0;
26646ce3c06aSMatthew G. Knepley         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
26656ce3c06aSMatthew G. Knepley         ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
26666ce3c06aSMatthew G. Knepley #if 1
26676ce3c06aSMatthew G. Knepley         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
26686ce3c06aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
26696ce3c06aSMatthew G. Knepley           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
26706ce3c06aSMatthew G. Knepley         }
26716ce3c06aSMatthew G. Knepley         for (p = 2; p < 4; ++p) {
26726ce3c06aSMatthew G. Knepley           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", coneNew[p], eMaxNew, eEndNew);
26736ce3c06aSMatthew G. Knepley         }
26746ce3c06aSMatthew G. Knepley #endif
26756ce3c06aSMatthew G. Knepley         for (s = 0; s < size; ++s) {
2676d3a1cc75SMatthew G. Knepley           const PetscInt *coneCell, *orntCell, *fornt;
26776ce3c06aSMatthew G. Knepley 
26786ce3c06aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &coneCell);CHKERRQ(ierr);
26796ce3c06aSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &orntCell);CHKERRQ(ierr);
26806ce3c06aSMatthew G. Knepley           for (c = 2; c < 5; ++c) if (coneCell[c] == f) break;
26816ce3c06aSMatthew G. Knepley           if (c >= 5) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of cell %d", f, support[s]);
2682d3a1cc75SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, coneCell[0], &fornt);CHKERRQ(ierr);
2683d3a1cc75SMatthew G. Knepley           supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetTriEdgeInverse_Static(orntCell[0], c-2) + (fornt[c-2] < 0 ? 1-r : r))%3;
26846ce3c06aSMatthew G. Knepley         }
26856ce3c06aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
26866ce3c06aSMatthew G. Knepley #if 1
26876ce3c06aSMatthew G. Knepley         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
26886ce3c06aSMatthew G. Knepley         for (p = 0; p < size; ++p) {
26896ce3c06aSMatthew G. Knepley           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", supportNew[p], cMaxNew, cEndNew);
26906ce3c06aSMatthew G. Knepley         }
26916ce3c06aSMatthew G. Knepley #endif
26926ce3c06aSMatthew G. Knepley       }
26936ce3c06aSMatthew G. Knepley     }
26946ce3c06aSMatthew G. Knepley     /* Hybrid cell faces have 4 edges and 2 cells */
26956ce3c06aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
26966ce3c06aSMatthew G. Knepley       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3;
26976ce3c06aSMatthew G. Knepley       const PetscInt *cone, *ornt;
26986ce3c06aSMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
26996ce3c06aSMatthew G. Knepley       PetscInt        supportNew[2];
27006ce3c06aSMatthew G. Knepley 
27016ce3c06aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
27026ce3c06aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
27036ce3c06aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
27046ce3c06aSMatthew G. Knepley         coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], (r+2)%3);
27056ce3c06aSMatthew G. Knepley         orntNew[0] = 0;
27066ce3c06aSMatthew G. Knepley         coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], (r+2)%3);
27076ce3c06aSMatthew G. Knepley         orntNew[1] = 0;
27086ce3c06aSMatthew G. Knepley         coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+GetTriSubface_Static(ornt[0], (r+2)%3)] - fMax);
27096ce3c06aSMatthew G. Knepley         orntNew[2] = 0;
27106ce3c06aSMatthew G. Knepley         coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+GetTriSubface_Static(ornt[0], r)]       - fMax);
27116ce3c06aSMatthew G. Knepley         orntNew[3] = 0;
27126ce3c06aSMatthew G. Knepley         ierr = DMPlexSetCone(rdm, newp+r, coneNew);CHKERRQ(ierr);
27136ce3c06aSMatthew G. Knepley         ierr = DMPlexSetConeOrientation(rdm, newp+r, orntNew);CHKERRQ(ierr);
27146ce3c06aSMatthew G. Knepley #if 1
27156ce3c06aSMatthew G. Knepley         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp+r, fMaxNew, fEndNew);
27166ce3c06aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
27176ce3c06aSMatthew G. Knepley           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
27186ce3c06aSMatthew G. Knepley         }
27196ce3c06aSMatthew G. Knepley         for (p = 2; p < 4; ++p) {
27206ce3c06aSMatthew G. Knepley           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", coneNew[p], eMaxNew, eEndNew);
27216ce3c06aSMatthew G. Knepley         }
27226ce3c06aSMatthew G. Knepley #endif
27236ce3c06aSMatthew G. Knepley         supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetTriSubface_Static(ornt[0], r);
27246ce3c06aSMatthew G. Knepley         supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + 3;
27256ce3c06aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp+r, supportNew);CHKERRQ(ierr);
27266ce3c06aSMatthew G. Knepley #if 1
27276ce3c06aSMatthew G. Knepley         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp+r, fMaxNew, fEndNew);
27286ce3c06aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
27296ce3c06aSMatthew G. Knepley           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", supportNew[p], cMaxNew, cEndNew);
27306ce3c06aSMatthew G. Knepley         }
27316ce3c06aSMatthew G. Knepley #endif
27326ce3c06aSMatthew G. Knepley       }
27336ce3c06aSMatthew G. Knepley     }
27346ce3c06aSMatthew G. Knepley     /* Interior split edges have 2 vertices and the same faces as the parent */
27356ce3c06aSMatthew G. Knepley     for (e = eStart; e < eMax; ++e) {
27366ce3c06aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
27376ce3c06aSMatthew G. Knepley 
27386ce3c06aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
27396ce3c06aSMatthew G. Knepley         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
27406ce3c06aSMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
27416ce3c06aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
27426ce3c06aSMatthew G. Knepley 
27436ce3c06aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
27446ce3c06aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
27456ce3c06aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
27466ce3c06aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
27476ce3c06aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
27486ce3c06aSMatthew G. Knepley #if 1
27496ce3c06aSMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
27506ce3c06aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
27516ce3c06aSMatthew 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);
27526ce3c06aSMatthew G. Knepley         }
27536ce3c06aSMatthew G. Knepley #endif
27546ce3c06aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
27556ce3c06aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
27566ce3c06aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
27576ce3c06aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
27586ce3c06aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
27596ce3c06aSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
27606ce3c06aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) if (cone[c] == e) break;
27616ce3c06aSMatthew G. Knepley           if (support[s] < fMax) {
27626ce3c06aSMatthew G. Knepley             supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
27636ce3c06aSMatthew G. Knepley           } else {
27646ce3c06aSMatthew G. Knepley             supportRef[s] = fStartNew + (fMax       - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
27656ce3c06aSMatthew G. Knepley           }
27666ce3c06aSMatthew G. Knepley         }
27676ce3c06aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
27686ce3c06aSMatthew G. Knepley #if 1
27696ce3c06aSMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
27706ce3c06aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
27716ce3c06aSMatthew G. Knepley           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid face [%d, %d)", supportRef[p], fStartNew, fEndNew);
27726ce3c06aSMatthew G. Knepley         }
27736ce3c06aSMatthew G. Knepley #endif
27746ce3c06aSMatthew G. Knepley       }
27756ce3c06aSMatthew G. Knepley     }
27766ce3c06aSMatthew G. Knepley     /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
27776ce3c06aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
27786ce3c06aSMatthew G. Knepley       const PetscInt *cone, *ornt, *support;
27796ce3c06aSMatthew G. Knepley       PetscInt        coneSize, supportSize, s;
27806ce3c06aSMatthew G. Knepley 
27816ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
27826ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
27836ce3c06aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
27846ce3c06aSMatthew G. Knepley         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
27856ce3c06aSMatthew G. Knepley         PetscInt        coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
27866ce3c06aSMatthew G. Knepley         PetscInt        fint[24] = { 1,  7, -1, -1,  0,  5,
27876ce3c06aSMatthew G. Knepley                                     -1, -1,  1,  6,  0,  4,
27886ce3c06aSMatthew G. Knepley                                      2,  5,  3,  4, -1, -1,
27896ce3c06aSMatthew G. Knepley                                     -1, -1,  3,  6,  2,  7};
27906ce3c06aSMatthew G. Knepley 
27916ce3c06aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
27926ce3c06aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
27936ce3c06aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
27946ce3c06aSMatthew G. Knepley         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
27956ce3c06aSMatthew G. Knepley #if 1
27966ce3c06aSMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
27976ce3c06aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
27986ce3c06aSMatthew 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);
27996ce3c06aSMatthew G. Knepley         }
28006ce3c06aSMatthew G. Knepley #endif
28016ce3c06aSMatthew G. Knepley         supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
28026ce3c06aSMatthew G. Knepley         supportRef[1] = fStartNew + (f - fStart)*4 + 3;
28036ce3c06aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
28046ce3c06aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
28056ce3c06aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
28066ce3c06aSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
28076ce3c06aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
28086ce3c06aSMatthew G. Knepley           if (support[s] < cMax) {
28096ce3c06aSMatthew G. Knepley             /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
28106ce3c06aSMatthew G. Knepley             er   = ornt[c] < 0 ? (-(ornt[c]+1) + 2-r)%3 : (ornt[c] + r)%3;
28116ce3c06aSMatthew G. Knepley             if (er == eint[c]) {
28126ce3c06aSMatthew G. Knepley               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
28136ce3c06aSMatthew G. Knepley             } else {
28146ce3c06aSMatthew G. Knepley               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
28156ce3c06aSMatthew G. Knepley               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
28166ce3c06aSMatthew G. Knepley             }
28176ce3c06aSMatthew G. Knepley           } else {
2818e515e2ddSMatthew G. Knepley             supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (GetTriSubfaceInverse_Static(ornt[c], r) + 1)%3;
28196ce3c06aSMatthew G. Knepley           }
28206ce3c06aSMatthew G. Knepley         }
28216ce3c06aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
28226ce3c06aSMatthew G. Knepley #if 1
28236ce3c06aSMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
28246ce3c06aSMatthew G. Knepley         for (p = 0; p < intFaces; ++p) {
28256ce3c06aSMatthew G. Knepley           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid face [%d, %d)", supportRef[p], fStartNew, fEndNew);
28266ce3c06aSMatthew G. Knepley         }
28276ce3c06aSMatthew G. Knepley #endif
28286ce3c06aSMatthew G. Knepley       }
28296ce3c06aSMatthew G. Knepley     }
28306ce3c06aSMatthew G. Knepley     /* Interior cell edges have 2 vertices and 4 faces */
28316ce3c06aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
28326ce3c06aSMatthew G. Knepley       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
28336ce3c06aSMatthew G. Knepley       const PetscInt *cone, *ornt, *fcone;
28346ce3c06aSMatthew G. Knepley       PetscInt        coneNew[2], supportNew[4], find;
28356ce3c06aSMatthew G. Knepley 
28366ce3c06aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
28376ce3c06aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
28386ce3c06aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, cone[0], &fcone);CHKERRQ(ierr);
28396ce3c06aSMatthew G. Knepley       find = GetTriEdge_Static(ornt[0], 0);
28406ce3c06aSMatthew G. Knepley       coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
28416ce3c06aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, cone[2], &fcone);CHKERRQ(ierr);
28426ce3c06aSMatthew G. Knepley       find = GetTriEdge_Static(ornt[2], 1);
28436ce3c06aSMatthew G. Knepley       coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
28446ce3c06aSMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
28456ce3c06aSMatthew G. Knepley #if 1
28466ce3c06aSMatthew G. Knepley       if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
28476ce3c06aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
28486ce3c06aSMatthew 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);
28496ce3c06aSMatthew G. Knepley       }
28506ce3c06aSMatthew G. Knepley #endif
28516ce3c06aSMatthew G. Knepley       supportNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
28526ce3c06aSMatthew G. Knepley       supportNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
28536ce3c06aSMatthew G. Knepley       supportNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
28546ce3c06aSMatthew G. Knepley       supportNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
28556ce3c06aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
28566ce3c06aSMatthew G. Knepley #if 1
28576ce3c06aSMatthew G. Knepley       if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
28586ce3c06aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
28596ce3c06aSMatthew G. Knepley         if ((supportNew[p] < fStartNew) || (supportNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportNew[p], fStartNew, fMaxNew);
28606ce3c06aSMatthew G. Knepley       }
28616ce3c06aSMatthew G. Knepley #endif
28626ce3c06aSMatthew G. Knepley     }
28636ce3c06aSMatthew G. Knepley     /* Hybrid edges have two vertices and the same faces */
28646ce3c06aSMatthew G. Knepley     for (e = eMax; e < eEnd; ++e) {
28656ce3c06aSMatthew G. Knepley       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
28666ce3c06aSMatthew G. Knepley       const PetscInt *cone, *support, *fcone;
28676ce3c06aSMatthew G. Knepley       PetscInt        coneNew[2], size, fsize, s;
28686ce3c06aSMatthew G. Knepley 
28696ce3c06aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
28706ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
28716ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
28726ce3c06aSMatthew G. Knepley       coneNew[0] = vStartNew + (cone[0] - vStart);
28736ce3c06aSMatthew G. Knepley       coneNew[1] = vStartNew + (cone[1] - vStart);
28746ce3c06aSMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
28756ce3c06aSMatthew G. Knepley #if 1
28766ce3c06aSMatthew G. Knepley       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
28776ce3c06aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
28786ce3c06aSMatthew 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);
28796ce3c06aSMatthew G. Knepley       }
28806ce3c06aSMatthew G. Knepley #endif
28816ce3c06aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
28826ce3c06aSMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, support[s], &fsize);CHKERRQ(ierr);
28836ce3c06aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &fcone);CHKERRQ(ierr);
28846ce3c06aSMatthew G. Knepley         for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
28856ce3c06aSMatthew G. Knepley         if ((c < 2) || (c > 3)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge %d not found in cone of face %d", e, support[s]);
28866ce3c06aSMatthew G. Knepley         supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + c-2;
28876ce3c06aSMatthew G. Knepley       }
28886ce3c06aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
28896ce3c06aSMatthew G. Knepley #if 1
28906ce3c06aSMatthew G. Knepley       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
28916ce3c06aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
28926ce3c06aSMatthew G. Knepley         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", supportRef[p], fMaxNew, fEndNew);
28936ce3c06aSMatthew G. Knepley       }
28946ce3c06aSMatthew G. Knepley #endif
28956ce3c06aSMatthew G. Knepley     }
28966ce3c06aSMatthew G. Knepley     /* Hybrid face edges have 2 vertices and 2+2*cells faces */
28976ce3c06aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
28986ce3c06aSMatthew G. Knepley       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
2899623f4348SMatthew G. Knepley       const PetscInt *cone, *support, *ccone, *cornt;
29006ce3c06aSMatthew G. Knepley       PetscInt        coneNew[2], size, csize, s;
29016ce3c06aSMatthew G. Knepley 
29026ce3c06aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
29036ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
29046ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
29056ce3c06aSMatthew G. Knepley       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
29066ce3c06aSMatthew G. Knepley       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
29076ce3c06aSMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
29086ce3c06aSMatthew G. Knepley #if 1
29096ce3c06aSMatthew G. Knepley       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
29106ce3c06aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
29116ce3c06aSMatthew 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);
29126ce3c06aSMatthew G. Knepley       }
29136ce3c06aSMatthew G. Knepley #endif
29146ce3c06aSMatthew G. Knepley       supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 0;
29156ce3c06aSMatthew G. Knepley       supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 1;
29166ce3c06aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
29176ce3c06aSMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, support[s], &csize);CHKERRQ(ierr);
29186ce3c06aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &ccone);CHKERRQ(ierr);
2919623f4348SMatthew G. Knepley         ierr = DMPlexGetConeOrientation(dm, support[s], &cornt);CHKERRQ(ierr);
29206ce3c06aSMatthew G. Knepley         for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
29216ce3c06aSMatthew G. Knepley         if ((c < 2) || (c >= csize)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Hybrid face %d is not in cone of hybrid cell %d", f, support[s]);
2922623f4348SMatthew G. Knepley         supportRef[2+s*2+0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + GetTriSubfaceInverse_Static(cornt[0], c-2);
2923623f4348SMatthew G. Knepley         supportRef[2+s*2+1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (GetTriSubfaceInverse_Static(cornt[0], c-2) + 1)%3;
29246ce3c06aSMatthew G. Knepley       }
29256ce3c06aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
29266ce3c06aSMatthew G. Knepley #if 1
29276ce3c06aSMatthew G. Knepley       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
29286ce3c06aSMatthew G. Knepley       for (p = 0; p < 2+size*2; ++p) {
29296ce3c06aSMatthew G. Knepley         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", supportRef[p], fMaxNew, fEndNew);
29306ce3c06aSMatthew G. Knepley       }
29316ce3c06aSMatthew G. Knepley #endif
29326ce3c06aSMatthew G. Knepley     }
29336ce3c06aSMatthew G. Knepley     /* Interior vertices have identical supports */
29346ce3c06aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
29356ce3c06aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
29366ce3c06aSMatthew G. Knepley       const PetscInt *support, *cone;
29376ce3c06aSMatthew G. Knepley       PetscInt        size, s;
29386ce3c06aSMatthew G. Knepley 
29396ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
29406ce3c06aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
29416ce3c06aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
29426ce3c06aSMatthew G. Knepley         PetscInt r = 0;
29436ce3c06aSMatthew G. Knepley 
29446ce3c06aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
29456ce3c06aSMatthew G. Knepley         if (cone[1] == v) r = 1;
29466ce3c06aSMatthew G. Knepley         if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
29476ce3c06aSMatthew G. Knepley         else                   supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (support[s] - eMax);
29486ce3c06aSMatthew G. Knepley       }
29496ce3c06aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
29506ce3c06aSMatthew G. Knepley #if 1
29516ce3c06aSMatthew 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);
29526ce3c06aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
29536ce3c06aSMatthew G. Knepley         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
29546ce3c06aSMatthew G. Knepley       }
29556ce3c06aSMatthew G. Knepley #endif
29566ce3c06aSMatthew G. Knepley     }
29576ce3c06aSMatthew G. Knepley     /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
29586ce3c06aSMatthew G. Knepley     for (e = eStart; e < eMax; ++e) {
29596ce3c06aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
29606ce3c06aSMatthew G. Knepley       const PetscInt *cone, *support;
29616ce3c06aSMatthew G. Knepley       PetscInt       *star = NULL, starSize, faceSize = 0, cellSize = 0, coneSize, size, s;
29626ce3c06aSMatthew G. Knepley 
29636ce3c06aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
29646ce3c06aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
29656ce3c06aSMatthew G. Knepley       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
29666ce3c06aSMatthew G. Knepley       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
29676ce3c06aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
29686ce3c06aSMatthew G. Knepley         PetscInt r = 0;
29696ce3c06aSMatthew G. Knepley 
29706ce3c06aSMatthew G. Knepley         if (support[s] < fMax) {
29716ce3c06aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
29726ce3c06aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
29736ce3c06aSMatthew G. Knepley           for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
29746ce3c06aSMatthew G. Knepley           supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
29756ce3c06aSMatthew G. Knepley           supportRef[2+faceSize+1] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
29766ce3c06aSMatthew G. Knepley           faceSize += 2;
29776ce3c06aSMatthew G. Knepley         } else {
29786ce3c06aSMatthew G. Knepley           supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (fMax       - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (support[s] - fMax);
29796ce3c06aSMatthew G. Knepley           ++faceSize;
29806ce3c06aSMatthew G. Knepley         }
29816ce3c06aSMatthew G. Knepley       }
29826ce3c06aSMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
29836ce3c06aSMatthew G. Knepley       for (s = 0; s < starSize*2; s += 2) {
29846ce3c06aSMatthew G. Knepley         const PetscInt *cone, *ornt;
29856ce3c06aSMatthew G. Knepley         PetscInt        e01, e23;
29866ce3c06aSMatthew G. Knepley 
29876ce3c06aSMatthew G. Knepley         if ((star[s] >= cStart) && (star[s] < cMax)) {
29886ce3c06aSMatthew G. Knepley           /* Check edge 0-1 */
29896ce3c06aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
29906ce3c06aSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
29916ce3c06aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
29926ce3c06aSMatthew G. Knepley           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
29936ce3c06aSMatthew G. Knepley           /* Check edge 2-3 */
29946ce3c06aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
29956ce3c06aSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
29966ce3c06aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
29976ce3c06aSMatthew G. Knepley           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
29986ce3c06aSMatthew G. Knepley           if ((e01 == e) || (e23 == e)) {supportRef[2+faceSize+cellSize++] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (star[s] - cStart);}
29996ce3c06aSMatthew G. Knepley         }
30006ce3c06aSMatthew G. Knepley       }
30016ce3c06aSMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
30026ce3c06aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
30036ce3c06aSMatthew G. Knepley #if 1
30046ce3c06aSMatthew 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);
30056ce3c06aSMatthew G. Knepley       for (p = 0; p < 2+faceSize+cellSize; ++p) {
30066ce3c06aSMatthew G. Knepley         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
30076ce3c06aSMatthew G. Knepley       }
30086ce3c06aSMatthew G. Knepley #endif
30096ce3c06aSMatthew G. Knepley     }
30106ce3c06aSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
30116ce3c06aSMatthew G. Knepley     ierr = DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);CHKERRQ(ierr);
30126ce3c06aSMatthew G. Knepley     break;
30132eabf88fSMatthew G. Knepley   case 6:
30142eabf88fSMatthew G. Knepley     /* Hex 3D */
30152eabf88fSMatthew G. Knepley     /*
30162eabf88fSMatthew G. Knepley      Bottom (viewed from top)    Top
30172eabf88fSMatthew G. Knepley      1---------2---------2       7---------2---------6
30182eabf88fSMatthew G. Knepley      |         |         |       |         |         |
30192eabf88fSMatthew G. Knepley      |    B    2    C    |       |    H    2    G    |
30202eabf88fSMatthew G. Knepley      |         |         |       |         |         |
30212eabf88fSMatthew G. Knepley      3----3----0----1----1       3----3----0----1----1
30222eabf88fSMatthew G. Knepley      |         |         |       |         |         |
30232eabf88fSMatthew G. Knepley      |    A    0    D    |       |    E    0    F    |
30242eabf88fSMatthew G. Knepley      |         |         |       |         |         |
30252eabf88fSMatthew G. Knepley      0---------0---------3       4---------0---------5
30262eabf88fSMatthew G. Knepley      */
30272eabf88fSMatthew G. Knepley     /* All cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
30282eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
30292eabf88fSMatthew G. Knepley       const PetscInt  newp = (c - cStart)*8;
30302eabf88fSMatthew G. Knepley       const PetscInt *cone, *ornt;
30312eabf88fSMatthew G. Knepley       PetscInt        coneNew[6], orntNew[6];
30322eabf88fSMatthew G. Knepley 
30332eabf88fSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
30342eabf88fSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
30352eabf88fSMatthew G. Knepley       /* A hex */
3036e3f8b1d6SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
30372eabf88fSMatthew G. Knepley       orntNew[0] = ornt[0];
30382eabf88fSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
30392eabf88fSMatthew G. Knepley       orntNew[1] = 0;
3040e3f8b1d6SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
30412eabf88fSMatthew G. Knepley       orntNew[2] = ornt[2];
30422eabf88fSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
30432eabf88fSMatthew G. Knepley       orntNew[3] = 0;
30442eabf88fSMatthew G. Knepley       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
30452eabf88fSMatthew G. Knepley       orntNew[4] = 0;
3046e3f8b1d6SMatthew G. Knepley       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
30472eabf88fSMatthew G. Knepley       orntNew[5] = ornt[5];
30482eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
30492eabf88fSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
30502eabf88fSMatthew G. Knepley #if 1
30512eabf88fSMatthew 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);
30522eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
30532eabf88fSMatthew 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);
30542eabf88fSMatthew G. Knepley       }
30552eabf88fSMatthew G. Knepley #endif
30562eabf88fSMatthew G. Knepley       /* B hex */
3057e3f8b1d6SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
30582eabf88fSMatthew G. Knepley       orntNew[0] = ornt[0];
30592eabf88fSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
30602eabf88fSMatthew G. Knepley       orntNew[1] = 0;
30612eabf88fSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
30622eabf88fSMatthew G. Knepley       orntNew[2] = -3;
3063e3f8b1d6SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
30642eabf88fSMatthew G. Knepley       orntNew[3] = ornt[3];
30652eabf88fSMatthew G. Knepley       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
30662eabf88fSMatthew G. Knepley       orntNew[4] = 0;
3067e3f8b1d6SMatthew G. Knepley       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
30682eabf88fSMatthew G. Knepley       orntNew[5] = ornt[5];
30692eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
30702eabf88fSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
30712eabf88fSMatthew G. Knepley #if 1
30722eabf88fSMatthew 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);
30732eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
30742eabf88fSMatthew 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);
30752eabf88fSMatthew G. Knepley       }
30762eabf88fSMatthew G. Knepley #endif
30772eabf88fSMatthew G. Knepley       /* C hex */
3078e3f8b1d6SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
30792eabf88fSMatthew G. Knepley       orntNew[0] = ornt[0];
30802eabf88fSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
30812eabf88fSMatthew G. Knepley       orntNew[1] = 0;
30822eabf88fSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
30832eabf88fSMatthew G. Knepley       orntNew[2] = 0;
3084e3f8b1d6SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
30852eabf88fSMatthew G. Knepley       orntNew[3] = ornt[3];
3086e3f8b1d6SMatthew G. Knepley       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
30872eabf88fSMatthew G. Knepley       orntNew[4] = ornt[4];
30882eabf88fSMatthew G. Knepley       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
30892eabf88fSMatthew G. Knepley       orntNew[5] = -3;
30902eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
30912eabf88fSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
30922eabf88fSMatthew G. Knepley #if 1
30932eabf88fSMatthew 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);
30942eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
30952eabf88fSMatthew 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);
30962eabf88fSMatthew G. Knepley       }
30972eabf88fSMatthew G. Knepley #endif
30982eabf88fSMatthew G. Knepley       /* D hex */
3099e3f8b1d6SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
31002eabf88fSMatthew G. Knepley       orntNew[0] = ornt[0];
31012eabf88fSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
31022eabf88fSMatthew G. Knepley       orntNew[1] = 0;
3103e3f8b1d6SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
31042eabf88fSMatthew G. Knepley       orntNew[2] = ornt[2];
31052eabf88fSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
31062eabf88fSMatthew G. Knepley       orntNew[3] = -3;
3107e3f8b1d6SMatthew G. Knepley       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
31082eabf88fSMatthew G. Knepley       orntNew[4] = ornt[4];
31092eabf88fSMatthew G. Knepley       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
31102eabf88fSMatthew G. Knepley       orntNew[5] = -3;
31112eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
31122eabf88fSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
31132eabf88fSMatthew G. Knepley #if 1
31142eabf88fSMatthew 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);
31152eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
31162eabf88fSMatthew 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);
31172eabf88fSMatthew G. Knepley       }
31182eabf88fSMatthew G. Knepley #endif
31192eabf88fSMatthew G. Knepley       /* E hex */
31202eabf88fSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
31212eabf88fSMatthew G. Knepley       orntNew[0] = -3;
3122e3f8b1d6SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
31232eabf88fSMatthew G. Knepley       orntNew[1] = ornt[1];
3124e3f8b1d6SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
31252eabf88fSMatthew G. Knepley       orntNew[2] = ornt[2];
31262eabf88fSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
31272eabf88fSMatthew G. Knepley       orntNew[3] = 0;
31282eabf88fSMatthew G. Knepley       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
31292eabf88fSMatthew G. Knepley       orntNew[4] = 0;
3130e3f8b1d6SMatthew G. Knepley       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
31312eabf88fSMatthew G. Knepley       orntNew[5] = ornt[5];
3132b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
3133b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
31342eabf88fSMatthew G. Knepley #if 1
3135b164cbf2SMatthew 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);
31362eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
31372eabf88fSMatthew 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);
31382eabf88fSMatthew G. Knepley       }
31392eabf88fSMatthew G. Knepley #endif
31402eabf88fSMatthew G. Knepley       /* F hex */
31412eabf88fSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
31422eabf88fSMatthew G. Knepley       orntNew[0] = -3;
3143e3f8b1d6SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
31442eabf88fSMatthew G. Knepley       orntNew[1] = ornt[1];
3145e3f8b1d6SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
31462eabf88fSMatthew G. Knepley       orntNew[2] = ornt[2];
31472eabf88fSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
31482eabf88fSMatthew G. Knepley       orntNew[3] = 0;
3149e3f8b1d6SMatthew G. Knepley       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
31502eabf88fSMatthew G. Knepley       orntNew[4] = ornt[4];
31512eabf88fSMatthew G. Knepley       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
31522eabf88fSMatthew G. Knepley       orntNew[5] = -3;
3153b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
3154b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
31552eabf88fSMatthew G. Knepley #if 1
3156b164cbf2SMatthew 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);
31572eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
31582eabf88fSMatthew 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);
31592eabf88fSMatthew G. Knepley       }
31602eabf88fSMatthew G. Knepley #endif
31612eabf88fSMatthew G. Knepley       /* G hex */
31622eabf88fSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
31632eabf88fSMatthew G. Knepley       orntNew[0] = -3;
3164e3f8b1d6SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
31652eabf88fSMatthew G. Knepley       orntNew[1] = ornt[1];
31662eabf88fSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
31672eabf88fSMatthew G. Knepley       orntNew[2] = -3;
3168e3f8b1d6SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
31692eabf88fSMatthew G. Knepley       orntNew[3] = ornt[3];
3170e3f8b1d6SMatthew G. Knepley       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
31712eabf88fSMatthew G. Knepley       orntNew[4] = ornt[4];
31722eabf88fSMatthew G. Knepley       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
31732eabf88fSMatthew G. Knepley       orntNew[5] = 0;
3174b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
3175b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
31762eabf88fSMatthew G. Knepley #if 1
3177b164cbf2SMatthew 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);
31782eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
31792eabf88fSMatthew 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);
31802eabf88fSMatthew G. Knepley       }
31812eabf88fSMatthew G. Knepley #endif
31822eabf88fSMatthew G. Knepley       /* H hex */
31832eabf88fSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
31842eabf88fSMatthew G. Knepley       orntNew[0] = -3;
3185e3f8b1d6SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
31862eabf88fSMatthew G. Knepley       orntNew[1] = ornt[1];
31872eabf88fSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
31882eabf88fSMatthew G. Knepley       orntNew[2] = -3;
3189e3f8b1d6SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
31902eabf88fSMatthew G. Knepley       orntNew[3] = ornt[3];
31912eabf88fSMatthew G. Knepley       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
31922eabf88fSMatthew G. Knepley       orntNew[4] = -3;
3193e3f8b1d6SMatthew G. Knepley       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
31942eabf88fSMatthew G. Knepley       orntNew[5] = ornt[5];
3195b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
3196b164cbf2SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
31972eabf88fSMatthew G. Knepley #if 1
3198b164cbf2SMatthew 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);
31992eabf88fSMatthew G. Knepley       for (p = 0; p < 6; ++p) {
32002eabf88fSMatthew 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);
32012eabf88fSMatthew G. Knepley       }
32022eabf88fSMatthew G. Knepley #endif
32032eabf88fSMatthew G. Knepley     }
32042eabf88fSMatthew G. Knepley     /* Split faces have 4 edges and the same cells as the parent */
32052eabf88fSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
32062eabf88fSMatthew G. Knepley     ierr = PetscMalloc((4 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
32072eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
32082eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
3209aaebbb9dSMatthew G. Knepley         /* TODO: This can come from GetFaces_Internal() */
32102eabf88fSMatthew 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};
32112eabf88fSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*4 + r;
32122eabf88fSMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
3213aaebbb9dSMatthew G. Knepley         PetscInt        coneNew[4], orntNew[4], coneSize, c, supportSize, s;
32142eabf88fSMatthew G. Knepley 
32152eabf88fSMatthew G. Knepley         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
3216aaebbb9dSMatthew G. Knepley         ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
3217aaebbb9dSMatthew G. Knepley         coneNew[0] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
3218aaebbb9dSMatthew G. Knepley         orntNew[0] = ornt[(r+3)%4];
3219aaebbb9dSMatthew G. Knepley         coneNew[1] = eStartNew + (cone[r]       - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
3220aaebbb9dSMatthew G. Knepley         orntNew[1] = ornt[r];
32212eabf88fSMatthew G. Knepley         coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
3222aaebbb9dSMatthew G. Knepley         orntNew[2] = 0;
32232eabf88fSMatthew G. Knepley         coneNew[3] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + (r+3)%4;
3224aaebbb9dSMatthew G. Knepley         orntNew[3] = -2;
32252eabf88fSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3226aaebbb9dSMatthew G. Knepley         ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
32272eabf88fSMatthew G. Knepley #if 1
32282eabf88fSMatthew 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);
32292eabf88fSMatthew G. Knepley         for (p = 0; p < 4; ++p) {
32302eabf88fSMatthew 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);
32312eabf88fSMatthew G. Knepley         }
32322eabf88fSMatthew G. Knepley #endif
32332eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
32342eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
32352eabf88fSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
32362eabf88fSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
32372eabf88fSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
32382eabf88fSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
32392eabf88fSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
32402eabf88fSMatthew G. Knepley             if (cone[c] == f) break;
32412eabf88fSMatthew G. Knepley           }
3242a3f78057SMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+GetQuadSubface_Static(ornt[c], r)];
32432eabf88fSMatthew G. Knepley         }
32442eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
32452eabf88fSMatthew G. Knepley #if 1
32462eabf88fSMatthew 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);
32472eabf88fSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
32482eabf88fSMatthew 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);
32492eabf88fSMatthew G. Knepley         }
32502eabf88fSMatthew G. Knepley #endif
32512eabf88fSMatthew G. Knepley       }
32522eabf88fSMatthew G. Knepley     }
32532eabf88fSMatthew G. Knepley     /* Interior faces have 4 edges and 2 cells */
32542eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
32552eabf88fSMatthew 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};
3256afb2665bSMatthew G. Knepley       const PetscInt *cone, *ornt;
3257afb2665bSMatthew G. Knepley       PetscInt        newp, coneNew[4], orntNew[4], supportNew[2];
32582eabf88fSMatthew G. Knepley 
32592eabf88fSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
3260afb2665bSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
3261afb2665bSMatthew G. Knepley       /* A-D face */
3262afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0;
3263afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
3264afb2665bSMatthew G. Knepley       orntNew[0] = -2;
3265afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
3266afb2665bSMatthew G. Knepley       orntNew[1] = 0;
3267afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
3268afb2665bSMatthew G. Knepley       orntNew[2] = 0;
3269afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
3270afb2665bSMatthew G. Knepley       orntNew[3] = -2;
32712eabf88fSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3272afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
32732eabf88fSMatthew G. Knepley #if 1
32742eabf88fSMatthew 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);
32752eabf88fSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
32762eabf88fSMatthew 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);
32772eabf88fSMatthew G. Knepley       }
32782eabf88fSMatthew G. Knepley #endif
3279afb2665bSMatthew G. Knepley       /* C-D face */
3280afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1;
3281afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
3282afb2665bSMatthew G. Knepley       orntNew[0] = -2;
3283afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
3284afb2665bSMatthew G. Knepley       orntNew[1] = 0;
3285afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
3286afb2665bSMatthew G. Knepley       orntNew[2] = 0;
3287afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
3288afb2665bSMatthew G. Knepley       orntNew[3] = -2;
3289afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3290afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3291afb2665bSMatthew G. Knepley #if 1
3292afb2665bSMatthew 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);
3293afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
3294afb2665bSMatthew 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);
3295afb2665bSMatthew G. Knepley       }
3296afb2665bSMatthew G. Knepley #endif
3297afb2665bSMatthew G. Knepley       /* B-C face */
3298afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2;
3299afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
3300afb2665bSMatthew G. Knepley       orntNew[0] = -2;
3301afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
3302afb2665bSMatthew G. Knepley       orntNew[1] = 0;
3303afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
3304afb2665bSMatthew G. Knepley       orntNew[2] = 0;
3305afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
3306afb2665bSMatthew G. Knepley       orntNew[3] = -2;
3307afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3308afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3309afb2665bSMatthew G. Knepley #if 1
3310afb2665bSMatthew 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);
3311afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
3312afb2665bSMatthew 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);
3313afb2665bSMatthew G. Knepley       }
3314afb2665bSMatthew G. Knepley #endif
3315afb2665bSMatthew G. Knepley       /* A-B face */
3316afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3;
3317afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
3318afb2665bSMatthew G. Knepley       orntNew[0] = -2;
3319afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
3320afb2665bSMatthew G. Knepley       orntNew[1] = 0;
3321afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
3322afb2665bSMatthew G. Knepley       orntNew[2] = 0;
3323afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
3324afb2665bSMatthew G. Knepley       orntNew[3] = -2;
3325afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3326afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3327afb2665bSMatthew G. Knepley #if 1
3328afb2665bSMatthew 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);
3329afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
3330afb2665bSMatthew 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);
3331afb2665bSMatthew G. Knepley       }
3332afb2665bSMatthew G. Knepley #endif
3333afb2665bSMatthew G. Knepley       /* E-F face */
3334afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4;
3335afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
3336afb2665bSMatthew G. Knepley       orntNew[0] = -2;
3337afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
3338afb2665bSMatthew G. Knepley       orntNew[1] = 0;
3339afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
3340afb2665bSMatthew G. Knepley       orntNew[2] = 0;
3341afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
3342afb2665bSMatthew G. Knepley       orntNew[3] = -2;
3343afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3344afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3345afb2665bSMatthew G. Knepley #if 1
3346afb2665bSMatthew 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);
3347afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
3348afb2665bSMatthew 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);
3349afb2665bSMatthew G. Knepley       }
3350afb2665bSMatthew G. Knepley #endif
3351afb2665bSMatthew G. Knepley       /* F-G face */
3352afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5;
3353afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
3354afb2665bSMatthew G. Knepley       orntNew[0] = -2;
3355afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
3356afb2665bSMatthew G. Knepley       orntNew[1] = 0;
3357afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
3358afb2665bSMatthew G. Knepley       orntNew[2] = 0;
3359afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
3360afb2665bSMatthew G. Knepley       orntNew[3] = -2;
3361afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3362afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3363afb2665bSMatthew G. Knepley #if 1
3364afb2665bSMatthew 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);
3365afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
3366afb2665bSMatthew 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);
3367afb2665bSMatthew G. Knepley       }
3368afb2665bSMatthew G. Knepley #endif
3369afb2665bSMatthew G. Knepley       /* G-H face */
3370afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6;
3371afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
3372afb2665bSMatthew G. Knepley       orntNew[0] = -2;
3373afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
3374afb2665bSMatthew G. Knepley       orntNew[1] = 0;
3375afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
3376afb2665bSMatthew G. Knepley       orntNew[2] = 0;
3377afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
3378afb2665bSMatthew G. Knepley       orntNew[3] = -2;
3379afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3380afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3381afb2665bSMatthew G. Knepley #if 1
3382afb2665bSMatthew 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);
3383afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
3384afb2665bSMatthew 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);
3385afb2665bSMatthew G. Knepley       }
3386afb2665bSMatthew G. Knepley #endif
3387afb2665bSMatthew G. Knepley       /* E-H face */
3388afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7;
3389afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
3390afb2665bSMatthew G. Knepley       orntNew[0] = -2;
3391afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
3392afb2665bSMatthew G. Knepley       orntNew[1] = 0;
3393afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
3394afb2665bSMatthew G. Knepley       orntNew[2] = 0;
3395afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
3396afb2665bSMatthew G. Knepley       orntNew[3] = -2;
3397afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3398afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3399afb2665bSMatthew G. Knepley #if 1
3400afb2665bSMatthew 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);
3401afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
3402afb2665bSMatthew 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);
3403afb2665bSMatthew G. Knepley       }
3404afb2665bSMatthew G. Knepley #endif
3405afb2665bSMatthew G. Knepley       /* A-E face */
3406afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8;
3407afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
3408afb2665bSMatthew G. Knepley       orntNew[0] = -2;
3409afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
3410afb2665bSMatthew G. Knepley       orntNew[1] = 0;
3411afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
3412afb2665bSMatthew G. Knepley       orntNew[2] = 0;
3413afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
3414afb2665bSMatthew G. Knepley       orntNew[3] = -2;
3415afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3416afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3417afb2665bSMatthew G. Knepley #if 1
3418afb2665bSMatthew 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);
3419afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
3420afb2665bSMatthew 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);
3421afb2665bSMatthew G. Knepley       }
3422afb2665bSMatthew G. Knepley #endif
3423afb2665bSMatthew G. Knepley       /* D-F face */
3424afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9;
3425afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
3426afb2665bSMatthew G. Knepley       orntNew[0] = -2;
3427afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
3428afb2665bSMatthew G. Knepley       orntNew[1] = 0;
3429afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
3430afb2665bSMatthew G. Knepley       orntNew[2] = 0;
3431afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
3432afb2665bSMatthew G. Knepley       orntNew[3] = -2;
3433afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3434afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3435afb2665bSMatthew G. Knepley #if 1
3436afb2665bSMatthew 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);
3437afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
3438afb2665bSMatthew 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);
3439afb2665bSMatthew G. Knepley       }
3440afb2665bSMatthew G. Knepley #endif
3441afb2665bSMatthew G. Knepley       /* C-G face */
3442afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10;
3443afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
3444afb2665bSMatthew G. Knepley       orntNew[0] = -2;
3445afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
3446afb2665bSMatthew G. Knepley       orntNew[1] = 0;
3447afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
3448afb2665bSMatthew G. Knepley       orntNew[2] = 0;
3449afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
3450afb2665bSMatthew G. Knepley       orntNew[3] = -2;
3451afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3452afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3453afb2665bSMatthew G. Knepley #if 1
3454afb2665bSMatthew 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);
3455afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
3456afb2665bSMatthew 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);
3457afb2665bSMatthew G. Knepley       }
3458afb2665bSMatthew G. Knepley #endif
3459afb2665bSMatthew G. Knepley       /* B-H face */
3460afb2665bSMatthew G. Knepley       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11;
3461afb2665bSMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
3462afb2665bSMatthew G. Knepley       orntNew[0] = -2;
3463afb2665bSMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
3464afb2665bSMatthew G. Knepley       orntNew[1] = 0;
3465afb2665bSMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
3466afb2665bSMatthew G. Knepley       orntNew[2] = 0;
3467afb2665bSMatthew G. Knepley       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
3468afb2665bSMatthew G. Knepley       orntNew[3] = -2;
3469afb2665bSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3470afb2665bSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3471afb2665bSMatthew G. Knepley #if 1
3472afb2665bSMatthew 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);
3473afb2665bSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
3474afb2665bSMatthew 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);
3475afb2665bSMatthew G. Knepley       }
3476afb2665bSMatthew G. Knepley #endif
3477afb2665bSMatthew G. Knepley       for (r = 0; r < 12; ++r) {
3478afb2665bSMatthew G. Knepley         newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
34792eabf88fSMatthew G. Knepley         supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
34802eabf88fSMatthew G. Knepley         supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
34812eabf88fSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
34822eabf88fSMatthew G. Knepley #if 1
34832eabf88fSMatthew 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);
34842eabf88fSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
34852eabf88fSMatthew 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);
34862eabf88fSMatthew G. Knepley         }
34872eabf88fSMatthew G. Knepley #endif
34882eabf88fSMatthew G. Knepley       }
34892eabf88fSMatthew G. Knepley     }
34902eabf88fSMatthew G. Knepley     /* Split edges have 2 vertices and the same faces as the parent */
34912eabf88fSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
34922eabf88fSMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
34932eabf88fSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
34942eabf88fSMatthew G. Knepley 
34952eabf88fSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
34962eabf88fSMatthew G. Knepley         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
34972eabf88fSMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
34982eabf88fSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
34992eabf88fSMatthew G. Knepley 
35002eabf88fSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
35012eabf88fSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
35022eabf88fSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
35032eabf88fSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
35042eabf88fSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
35052eabf88fSMatthew G. Knepley #if 1
35062eabf88fSMatthew 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);
35072eabf88fSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
35082eabf88fSMatthew 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);
35092eabf88fSMatthew G. Knepley         }
35102eabf88fSMatthew G. Knepley #endif
35112eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
35122eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
35132eabf88fSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
35142eabf88fSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
35152eabf88fSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
35162eabf88fSMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
35172eabf88fSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
35182eabf88fSMatthew G. Knepley             if (cone[c] == e) break;
35192eabf88fSMatthew G. Knepley           }
35202eabf88fSMatthew G. Knepley           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
35212eabf88fSMatthew G. Knepley         }
35222eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
35232eabf88fSMatthew G. Knepley #if 1
35242eabf88fSMatthew 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);
35252eabf88fSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
35262eabf88fSMatthew 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);
35272eabf88fSMatthew G. Knepley         }
35282eabf88fSMatthew G. Knepley #endif
35292eabf88fSMatthew G. Knepley       }
35302eabf88fSMatthew G. Knepley     }
35312eabf88fSMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells faces */
35322eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
35336b852384SMatthew G. Knepley       const PetscInt  newFaces[24] = {3, 2, 1, 0,  4, 5, 6, 7,  0, 9, 4, 8,  2, 11, 6, 10,  1, 10, 5, 9,  8, 7, 11, 3};
35342eabf88fSMatthew G. Knepley       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
35356b852384SMatthew G. Knepley       const PetscInt *cone, *coneCell, *orntCell, *support;
35362eabf88fSMatthew G. Knepley       PetscInt        coneNew[2], coneSize, c, supportSize, s;
35372eabf88fSMatthew G. Knepley 
35382eabf88fSMatthew G. Knepley       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
35392eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
35402eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
35412eabf88fSMatthew G. Knepley 
35422eabf88fSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
35432eabf88fSMatthew G. Knepley         coneNew[1] = newv;
35442eabf88fSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
35452eabf88fSMatthew G. Knepley #if 1
35462eabf88fSMatthew 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);
35472eabf88fSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
35482eabf88fSMatthew 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);
35492eabf88fSMatthew G. Knepley         }
35502eabf88fSMatthew G. Knepley #endif
35512eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
35522eabf88fSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
35532eabf88fSMatthew G. Knepley         supportRef[0] = fStartNew + (f - fStart)*4 + r;
35542eabf88fSMatthew G. Knepley         supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
35552eabf88fSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
35566b852384SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
35576b852384SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &coneCell);CHKERRQ(ierr);
35586b852384SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &orntCell);CHKERRQ(ierr);
35592eabf88fSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
35606b852384SMatthew G. Knepley           supportRef[2+s] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdge_Static(orntCell[c], r)];
35612eabf88fSMatthew G. Knepley         }
35622eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
35632eabf88fSMatthew G. Knepley #if 1
35642eabf88fSMatthew 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);
35652eabf88fSMatthew G. Knepley         for (p = 0; p < 2+supportSize; ++p) {
35662eabf88fSMatthew 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);
35672eabf88fSMatthew G. Knepley         }
35682eabf88fSMatthew G. Knepley #endif
35692eabf88fSMatthew G. Knepley       }
35702eabf88fSMatthew G. Knepley     }
35712eabf88fSMatthew G. Knepley     /* Cell edges have 2 vertices and 4 faces */
35722eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
35732eabf88fSMatthew 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};
35742eabf88fSMatthew G. Knepley       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
35752eabf88fSMatthew G. Knepley       const PetscInt *cone;
35762eabf88fSMatthew G. Knepley       PetscInt        coneNew[2], supportNew[4];
35772eabf88fSMatthew G. Knepley 
35782eabf88fSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
35792eabf88fSMatthew G. Knepley       for (r = 0; r < 6; ++r) {
35802eabf88fSMatthew G. Knepley         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
35812eabf88fSMatthew G. Knepley 
35822eabf88fSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
35832eabf88fSMatthew G. Knepley         coneNew[1] = newv;
35842eabf88fSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
35852eabf88fSMatthew G. Knepley #if 1
35862eabf88fSMatthew 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);
35872eabf88fSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
35882eabf88fSMatthew 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);
35892eabf88fSMatthew G. Knepley         }
35902eabf88fSMatthew G. Knepley #endif
35912eabf88fSMatthew G. Knepley         for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
35922eabf88fSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
35932eabf88fSMatthew G. Knepley #if 1
35942eabf88fSMatthew 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);
35952eabf88fSMatthew G. Knepley         for (p = 0; p < 4; ++p) {
35962eabf88fSMatthew 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);
35972eabf88fSMatthew G. Knepley         }
35982eabf88fSMatthew G. Knepley #endif
35992eabf88fSMatthew G. Knepley       }
36002eabf88fSMatthew G. Knepley     }
36012eabf88fSMatthew G. Knepley     /* Old vertices have identical supports */
36022eabf88fSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
36032eabf88fSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
36042eabf88fSMatthew G. Knepley       const PetscInt *support, *cone;
36052eabf88fSMatthew G. Knepley       PetscInt        size, s;
36062eabf88fSMatthew G. Knepley 
36072eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
36082eabf88fSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
36092eabf88fSMatthew G. Knepley       for (s = 0; s < size; ++s) {
36102eabf88fSMatthew G. Knepley         PetscInt r = 0;
36112eabf88fSMatthew G. Knepley 
36122eabf88fSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
36132eabf88fSMatthew G. Knepley         if (cone[1] == v) r = 1;
36142eabf88fSMatthew G. Knepley         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
36152eabf88fSMatthew G. Knepley       }
36162eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
36172eabf88fSMatthew G. Knepley #if 1
36182eabf88fSMatthew 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);
36192eabf88fSMatthew G. Knepley       for (p = 0; p < size; ++p) {
36202eabf88fSMatthew 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);
36212eabf88fSMatthew G. Knepley       }
36222eabf88fSMatthew G. Knepley #endif
36232eabf88fSMatthew G. Knepley     }
36242eabf88fSMatthew G. Knepley     /* Edge vertices have 2 + faces supports */
36252eabf88fSMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
36262eabf88fSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
36272eabf88fSMatthew G. Knepley       const PetscInt *cone, *support;
36282eabf88fSMatthew G. Knepley       PetscInt        size, s;
36292eabf88fSMatthew G. Knepley 
36302eabf88fSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
36312eabf88fSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
36322eabf88fSMatthew G. Knepley       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
36332eabf88fSMatthew G. Knepley       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
36342eabf88fSMatthew G. Knepley       for (s = 0; s < size; ++s) {
36352eabf88fSMatthew G. Knepley         PetscInt r;
36362eabf88fSMatthew G. Knepley 
36372eabf88fSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3638a660e16cSMatthew G. Knepley         for (r = 0; r < 4; ++r) if (cone[r] == e) break;
36392eabf88fSMatthew G. Knepley         supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*4 + r;
36402eabf88fSMatthew G. Knepley       }
36412eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
36422eabf88fSMatthew G. Knepley #if 1
36432eabf88fSMatthew 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);
36442eabf88fSMatthew G. Knepley       for (p = 0; p < 2+size; ++p) {
36452eabf88fSMatthew 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);
36462eabf88fSMatthew G. Knepley       }
36472eabf88fSMatthew G. Knepley #endif
36482eabf88fSMatthew G. Knepley     }
36492eabf88fSMatthew G. Knepley     /* Face vertices have 4 + cells supports */
36502eabf88fSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
36512eabf88fSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
36522eabf88fSMatthew G. Knepley       const PetscInt *cone, *support;
36532eabf88fSMatthew G. Knepley       PetscInt        size, s;
36542eabf88fSMatthew G. Knepley 
36552eabf88fSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
36562eabf88fSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
36572eabf88fSMatthew G. Knepley       for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (e - eStart)*2 +  (f - fStart)*4 + r;
36582eabf88fSMatthew G. Knepley       for (s = 0; s < size; ++s) {
36592eabf88fSMatthew G. Knepley         PetscInt r;
36602eabf88fSMatthew G. Knepley 
36612eabf88fSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
36622eabf88fSMatthew G. Knepley         for (r = 0; r < 6; ++r) if (cone[r] == f) break;
36632eabf88fSMatthew G. Knepley         supportRef[4+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (support[s] - cStart)*6 + r;
36642eabf88fSMatthew G. Knepley       }
36652eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
36662eabf88fSMatthew G. Knepley #if 1
36672eabf88fSMatthew 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);
36682eabf88fSMatthew G. Knepley       for (p = 0; p < 4+size; ++p) {
36692eabf88fSMatthew 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);
36702eabf88fSMatthew G. Knepley       }
36712eabf88fSMatthew G. Knepley #endif
36722eabf88fSMatthew G. Knepley     }
36732eabf88fSMatthew G. Knepley     /* Cell vertices have 6 supports */
36742eabf88fSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
36752eabf88fSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
36762eabf88fSMatthew G. Knepley       PetscInt       supportNew[6];
36772eabf88fSMatthew G. Knepley 
36782eabf88fSMatthew G. Knepley       for (r = 0; r < 6; ++r) {
36792eabf88fSMatthew G. Knepley         supportNew[r] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
36802eabf88fSMatthew G. Knepley       }
36812eabf88fSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
36822eabf88fSMatthew G. Knepley     }
3683da00770fSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
36842eabf88fSMatthew G. Knepley     break;
368575d3a19aSMatthew G. Knepley   default:
368675d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
368775d3a19aSMatthew G. Knepley   }
368875d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
368975d3a19aSMatthew G. Knepley }
369075d3a19aSMatthew G. Knepley 
369175d3a19aSMatthew G. Knepley #undef __FUNCT__
369275d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetCoordinates"
369375d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
369475d3a19aSMatthew G. Knepley {
369575d3a19aSMatthew G. Knepley   PetscSection   coordSection, coordSectionNew;
369675d3a19aSMatthew G. Knepley   Vec            coordinates, coordinatesNew;
369775d3a19aSMatthew G. Knepley   PetscScalar   *coords, *coordsNew;
36983478d7aaSMatthew G. Knepley   const PetscInt numVertices = depthSize ? depthSize[0] : 0;
3699b5da9499SMatthew G. Knepley   PetscInt       dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, eStart, eEnd, eMax, e, fStart, fEnd, fMax, f;
370075d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
370175d3a19aSMatthew G. Knepley 
370275d3a19aSMatthew G. Knepley   PetscFunctionBegin;
370375d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
370475d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
370575d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
3706b5da9499SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
370775d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
370875d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
3709b5da9499SMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, &eMax, NULL);CHKERRQ(ierr);
37103478d7aaSMatthew G. Knepley   if (refiner) {ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr);}
371175d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr);
371275d3a19aSMatthew G. Knepley   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
371375d3a19aSMatthew G. Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr);
371475d3a19aSMatthew G. Knepley   ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr);
371575d3a19aSMatthew G. Knepley   ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr);
37163478d7aaSMatthew G. Knepley   ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+numVertices);CHKERRQ(ierr);
371775d3a19aSMatthew G. Knepley   if (fMax < 0) fMax = fEnd;
3718b5da9499SMatthew G. Knepley   if (eMax < 0) eMax = eEnd;
371975d3a19aSMatthew G. Knepley   /* All vertices have the dim coordinates */
37203478d7aaSMatthew G. Knepley   for (v = vStartNew; v < vStartNew+numVertices; ++v) {
372175d3a19aSMatthew G. Knepley     ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr);
372275d3a19aSMatthew G. Knepley     ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr);
372375d3a19aSMatthew G. Knepley   }
372475d3a19aSMatthew G. Knepley   ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr);
372575d3a19aSMatthew G. Knepley   ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr);
372675d3a19aSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
372775d3a19aSMatthew G. Knepley   ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr);
372875d3a19aSMatthew G. Knepley   ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr);
372975d3a19aSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr);
373075d3a19aSMatthew G. Knepley   ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr);
373175d3a19aSMatthew G. Knepley   ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr);
373275d3a19aSMatthew G. Knepley   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
373375d3a19aSMatthew G. Knepley   ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
3734b5da9499SMatthew G. Knepley   switch (refiner) {
37353478d7aaSMatthew G. Knepley   case 0: break;
3736b5da9499SMatthew G. Knepley   case 6: /* Hex 3D */
3737b5da9499SMatthew G. Knepley     /* Face vertices have the average of corner coordinates */
3738b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
3739c91acedaSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
3740b5da9499SMatthew G. Knepley       PetscInt      *cone = NULL;
3741b5da9499SMatthew G. Knepley       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;
3742b5da9499SMatthew G. Knepley 
3743b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
3744b5da9499SMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
3745b5da9499SMatthew G. Knepley         const PetscInt point = cone[p];
3746b5da9499SMatthew G. Knepley         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
3747b5da9499SMatthew G. Knepley       }
3748b5da9499SMatthew G. Knepley       for (v = 0; v < coneSize; ++v) {
3749b5da9499SMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[v], &off[v]);CHKERRQ(ierr);
3750b5da9499SMatthew G. Knepley       }
3751b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
3752b5da9499SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
3753b5da9499SMatthew G. Knepley         coordsNew[offnew+d] = 0.0;
3754b5da9499SMatthew G. Knepley         for (v = 0; v < coneSize; ++v) coordsNew[offnew+d] += coords[off[v]+d];
3755b5da9499SMatthew G. Knepley         coordsNew[offnew+d] /= coneSize;
3756b5da9499SMatthew G. Knepley       }
3757b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
3758b5da9499SMatthew G. Knepley     }
3759b5da9499SMatthew G. Knepley   case 2: /* Hex 2D */
3760b5da9499SMatthew G. Knepley     /* Cell vertices have the average of corner coordinates */
3761b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
3762c91acedaSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (c - cStart) + (dim > 2 ? (fEnd - fStart) : 0);
3763b5da9499SMatthew G. Knepley       PetscInt      *cone = NULL;
3764b5da9499SMatthew G. Knepley       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;
3765b5da9499SMatthew G. Knepley 
3766b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
3767b5da9499SMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
3768b5da9499SMatthew G. Knepley         const PetscInt point = cone[p];
3769b5da9499SMatthew G. Knepley         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
3770b5da9499SMatthew G. Knepley       }
3771b5da9499SMatthew G. Knepley       for (v = 0; v < coneSize; ++v) {
3772b5da9499SMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[v], &off[v]);CHKERRQ(ierr);
3773b5da9499SMatthew G. Knepley       }
3774b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
3775b5da9499SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
3776b5da9499SMatthew G. Knepley         coordsNew[offnew+d] = 0.0;
3777b5da9499SMatthew G. Knepley         for (v = 0; v < coneSize; ++v) coordsNew[offnew+d] += coords[off[v]+d];
3778b5da9499SMatthew G. Knepley         coordsNew[offnew+d] /= coneSize;
3779b5da9499SMatthew G. Knepley       }
3780b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
3781b5da9499SMatthew G. Knepley     }
3782b5da9499SMatthew G. Knepley   case 1: /* Simplicial 2D */
3783b5da9499SMatthew G. Knepley   case 3: /* Hybrid Simplicial 2D */
3784b5da9499SMatthew G. Knepley   case 5: /* Simplicial 3D */
37856ce3c06aSMatthew G. Knepley   case 7: /* Hybrid Simplicial 3D */
3786b5da9499SMatthew G. Knepley     /* Edge vertices have the average of endpoint coordinates */
3787b5da9499SMatthew G. Knepley     for (e = eStart; e < eMax; ++e) {
3788b5da9499SMatthew G. Knepley       const PetscInt  newv = vStartNew + (vEnd - vStart) + (e - eStart);
3789b5da9499SMatthew G. Knepley       const PetscInt *cone;
3790b5da9499SMatthew G. Knepley       PetscInt        coneSize, offA, offB, offnew, d;
3791b5da9499SMatthew G. Knepley 
3792b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr);
3793b5da9499SMatthew G. Knepley       if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize);
3794b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
3795b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
3796b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
3797b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
3798b5da9499SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
3799b5da9499SMatthew G. Knepley         coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]);
3800b5da9499SMatthew G. Knepley       }
3801b5da9499SMatthew G. Knepley     }
380275d3a19aSMatthew G. Knepley     /* Old vertices have the same coordinates */
380375d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
380475d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (v - vStart);
380575d3a19aSMatthew G. Knepley       PetscInt       off, offnew, d;
380675d3a19aSMatthew G. Knepley 
380775d3a19aSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
380875d3a19aSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
380975d3a19aSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
381075d3a19aSMatthew G. Knepley         coordsNew[offnew+d] = coords[off+d];
381175d3a19aSMatthew G. Knepley       }
381275d3a19aSMatthew G. Knepley     }
3813b5da9499SMatthew G. Knepley     break;
3814b5da9499SMatthew G. Knepley   default:
3815b5da9499SMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
381675d3a19aSMatthew G. Knepley   }
381775d3a19aSMatthew G. Knepley   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
381875d3a19aSMatthew G. Knepley   ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
381975d3a19aSMatthew G. Knepley   ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr);
382075d3a19aSMatthew G. Knepley   ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr);
382175d3a19aSMatthew G. Knepley   ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr);
382275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
382375d3a19aSMatthew G. Knepley }
382475d3a19aSMatthew G. Knepley 
382575d3a19aSMatthew G. Knepley #undef __FUNCT__
382675d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexCreateProcessSF"
382775d3a19aSMatthew G. Knepley PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
382875d3a19aSMatthew G. Knepley {
382975d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, l;
383075d3a19aSMatthew G. Knepley   const PetscInt    *localPoints;
383175d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
383275d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
383375d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
383475d3a19aSMatthew G. Knepley   PetscInt          *ranks, *ranksNew;
383575d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
383675d3a19aSMatthew G. Knepley 
383775d3a19aSMatthew G. Knepley   PetscFunctionBegin;
383875d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
383975d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr);
384075d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
384175d3a19aSMatthew G. Knepley     ranks[l] = remotePoints[l].rank;
384275d3a19aSMatthew G. Knepley   }
384375d3a19aSMatthew G. Knepley   ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr);
384475d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt),    &ranksNew);CHKERRQ(ierr);
384575d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt),    &localPointsNew);CHKERRQ(ierr);
384675d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr);
384775d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
384875d3a19aSMatthew G. Knepley     ranksNew[l]              = ranks[l];
384975d3a19aSMatthew G. Knepley     localPointsNew[l]        = l;
385075d3a19aSMatthew G. Knepley     remotePointsNew[l].index = 0;
385175d3a19aSMatthew G. Knepley     remotePointsNew[l].rank  = ranksNew[l];
385275d3a19aSMatthew G. Knepley   }
385375d3a19aSMatthew G. Knepley   ierr = PetscFree(ranks);CHKERRQ(ierr);
385475d3a19aSMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);
385575d3a19aSMatthew G. Knepley   ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr);
385675d3a19aSMatthew G. Knepley   ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr);
385775d3a19aSMatthew G. Knepley   ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
385875d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
385975d3a19aSMatthew G. Knepley }
386075d3a19aSMatthew G. Knepley 
386175d3a19aSMatthew G. Knepley #undef __FUNCT__
386275d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerCreateSF"
386375d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
386475d3a19aSMatthew G. Knepley {
386575d3a19aSMatthew G. Knepley   PetscSF            sf, sfNew, sfProcess;
386675d3a19aSMatthew G. Knepley   IS                 processRanks;
386775d3a19aSMatthew G. Knepley   MPI_Datatype       depthType;
386875d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
386975d3a19aSMatthew G. Knepley   const PetscInt    *localPoints, *neighbors;
387075d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
387175d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
387275d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
387375d3a19aSMatthew G. Knepley   PetscInt          *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
3874*c3a233c8SMatthew G. Knepley   PetscInt           depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew = 0, cEnd, cMax, vStart, vStartNew = 0, vEnd, vMax, fStart, fStartNew = 0, fEnd, fMax, eStart, eStartNew = 0, eEnd, eMax, r, n;
387575d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
387675d3a19aSMatthew G. Knepley 
387775d3a19aSMatthew G. Knepley   PetscFunctionBegin;
387875d3a19aSMatthew G. Knepley   ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr);
387975d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
388075d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
388175d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
388275d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
388375d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
388475d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
38853478d7aaSMatthew G. Knepley   if (refiner) {ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);}
388675d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
388775d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr);
388875d3a19aSMatthew G. Knepley   /* Caculate size of new SF */
388975d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
389075d3a19aSMatthew G. Knepley   if (numRoots < 0) PetscFunctionReturn(0);
389175d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
389275d3a19aSMatthew G. Knepley     const PetscInt p = localPoints[l];
389375d3a19aSMatthew G. Knepley 
389475d3a19aSMatthew G. Knepley     switch (refiner) {
389575d3a19aSMatthew G. Knepley     case 1:
389675d3a19aSMatthew G. Knepley       /* Simplicial 2D */
389775d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
389875d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
389975d3a19aSMatthew G. Knepley         ++numLeavesNew;
390075d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
390175d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
3902d963de37SMatthew G. Knepley         numLeavesNew += 2 + 1;
390375d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
390475d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
390575d3a19aSMatthew G. Knepley         numLeavesNew += 4 + 3;
390675d3a19aSMatthew G. Knepley       }
390775d3a19aSMatthew G. Knepley       break;
390875d3a19aSMatthew G. Knepley     case 2:
390975d3a19aSMatthew G. Knepley       /* Hex 2D */
391075d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
391175d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
391275d3a19aSMatthew G. Knepley         ++numLeavesNew;
391375d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
391475d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
3915d963de37SMatthew G. Knepley         numLeavesNew += 2 + 1;
391675d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
3917455d6cd4SMatthew G. Knepley         /* Old cells add new cells, interior faces, and vertex */
3918455d6cd4SMatthew G. Knepley         numLeavesNew += 4 + 4 + 1;
391975d3a19aSMatthew G. Knepley       }
392075d3a19aSMatthew G. Knepley       break;
3921b5da9499SMatthew G. Knepley     case 5:
3922b5da9499SMatthew G. Knepley       /* Simplicial 3D */
3923b5da9499SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
3924b5da9499SMatthew G. Knepley         /* Old vertices stay the same */
3925b5da9499SMatthew G. Knepley         ++numLeavesNew;
3926b5da9499SMatthew G. Knepley       } else if ((p >= eStart) && (p < eEnd)) {
3927b5da9499SMatthew G. Knepley         /* Old edges add new edges and vertex */
3928b5da9499SMatthew G. Knepley         numLeavesNew += 2 + 1;
3929b5da9499SMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
3930b5da9499SMatthew G. Knepley         /* Old faces add new faces and face edges */
3931b5da9499SMatthew G. Knepley         numLeavesNew += 4 + 3;
3932b5da9499SMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
3933b5da9499SMatthew G. Knepley         /* Old cells add new cells and interior faces and edges */
3934b5da9499SMatthew G. Knepley         numLeavesNew += 8 + 8 + 1;
3935b5da9499SMatthew G. Knepley       }
3936b5da9499SMatthew G. Knepley       break;
39376ce3c06aSMatthew G. Knepley     case 7:
39386ce3c06aSMatthew G. Knepley       /* Hybrid Simplicial 3D */
39396ce3c06aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
39406ce3c06aSMatthew G. Knepley         /* Interior vertices stay the same */
39416ce3c06aSMatthew G. Knepley         ++numLeavesNew;
39426ce3c06aSMatthew G. Knepley       } else if ((p >= eStart) && (p < eMax)) {
39436ce3c06aSMatthew G. Knepley         /* Interior edges add new edges and vertex */
39446ce3c06aSMatthew G. Knepley         numLeavesNew += 2 + 1;
39456ce3c06aSMatthew G. Knepley       } else if ((p >= eMax) && (p < eEnd)) {
39466ce3c06aSMatthew G. Knepley         /* Hybrid edges stay the same */
39476ce3c06aSMatthew G. Knepley         ++numLeavesNew;
39486ce3c06aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fMax)) {
39496ce3c06aSMatthew G. Knepley         /* Interior faces add new faces and edges */
39506ce3c06aSMatthew G. Knepley         numLeavesNew += 4 + 3;
39516ce3c06aSMatthew G. Knepley       } else if ((p >= fMax) && (p < fEnd)) {
39526ce3c06aSMatthew G. Knepley         /* Hybrid faces add new faces and edges */
39536ce3c06aSMatthew G. Knepley         numLeavesNew += 2 + 1;
39546ce3c06aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cMax)) {
39556ce3c06aSMatthew G. Knepley         /* Interior cells add new cells, faces, and edges */
39566ce3c06aSMatthew G. Knepley         numLeavesNew += 8 + 8 + 1;
39576ce3c06aSMatthew G. Knepley       } else if ((p >= cMax) && (p < cEnd)) {
39586ce3c06aSMatthew G. Knepley         /* Hybrid cells add new cells and faces */
39596ce3c06aSMatthew G. Knepley         numLeavesNew += 4 + 3;
39606ce3c06aSMatthew G. Knepley       }
39616ce3c06aSMatthew G. Knepley       break;
39622eabf88fSMatthew G. Knepley     case 6:
39632eabf88fSMatthew G. Knepley       /* Hex 3D */
39642eabf88fSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
39652eabf88fSMatthew G. Knepley         /* Old vertices stay the same */
39662eabf88fSMatthew G. Knepley         ++numLeavesNew;
39672eabf88fSMatthew G. Knepley       } else if ((p >= eStart) && (p < eEnd)) {
39682eabf88fSMatthew G. Knepley         /* Old edges add new edges, and vertex */
39692eabf88fSMatthew G. Knepley         numLeavesNew += 2 + 1;
39702eabf88fSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
39712eabf88fSMatthew G. Knepley         /* Old faces add new faces, edges, and vertex */
39722eabf88fSMatthew G. Knepley         numLeavesNew += 4 + 4 + 1;
39732eabf88fSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
39742eabf88fSMatthew G. Knepley         /* Old cells add new cells, faces, edges, and vertex */
39752eabf88fSMatthew G. Knepley         numLeavesNew += 8 + 12 + 6 + 1;
39762eabf88fSMatthew G. Knepley       }
39772eabf88fSMatthew G. Knepley       break;
397875d3a19aSMatthew G. Knepley     default:
397975d3a19aSMatthew G. Knepley       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
398075d3a19aSMatthew G. Knepley     }
398175d3a19aSMatthew G. Knepley   }
398275d3a19aSMatthew G. Knepley   /* Communicate depthSizes for each remote rank */
398375d3a19aSMatthew G. Knepley   ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr);
398475d3a19aSMatthew G. Knepley   ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr);
398575d3a19aSMatthew G. Knepley   ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr);
398675d3a19aSMatthew 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);
398775d3a19aSMatthew G. Knepley   ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr);
398875d3a19aSMatthew G. Knepley   ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr);
398975d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
399075d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
399175d3a19aSMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {
399275d3a19aSMatthew G. Knepley     ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr);
399375d3a19aSMatthew G. Knepley   }
399475d3a19aSMatthew G. Knepley   depthSizeOld[depth]   = cMax;
399575d3a19aSMatthew G. Knepley   depthSizeOld[0]       = vMax;
399675d3a19aSMatthew G. Knepley   depthSizeOld[depth-1] = fMax;
399775d3a19aSMatthew G. Knepley   depthSizeOld[1]       = eMax;
399875d3a19aSMatthew G. Knepley 
399975d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
400075d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
400175d3a19aSMatthew G. Knepley 
400275d3a19aSMatthew G. Knepley   depthSizeOld[depth]   = cEnd - cStart;
400375d3a19aSMatthew G. Knepley   depthSizeOld[0]       = vEnd - vStart;
400475d3a19aSMatthew G. Knepley   depthSizeOld[depth-1] = fEnd - fStart;
400575d3a19aSMatthew G. Knepley   depthSizeOld[1]       = eEnd - eStart;
400675d3a19aSMatthew G. Knepley 
400775d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
400875d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
400975d3a19aSMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {
401075d3a19aSMatthew G. Knepley     ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr);
401175d3a19aSMatthew G. Knepley   }
401275d3a19aSMatthew G. Knepley   ierr = MPI_Type_free(&depthType);CHKERRQ(ierr);
401375d3a19aSMatthew G. Knepley   ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr);
401475d3a19aSMatthew G. Knepley   /* Calculate new point SF */
401575d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt),    &localPointsNew);CHKERRQ(ierr);
401675d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr);
401775d3a19aSMatthew G. Knepley   ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr);
401875d3a19aSMatthew G. Knepley   for (l = 0, m = 0; l < numLeaves; ++l) {
401975d3a19aSMatthew G. Knepley     PetscInt    p     = localPoints[l];
402075d3a19aSMatthew G. Knepley     PetscInt    rp    = remotePoints[l].index, n;
402175d3a19aSMatthew G. Knepley     PetscMPIInt rrank = remotePoints[l].rank;
402275d3a19aSMatthew G. Knepley 
402375d3a19aSMatthew G. Knepley     ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr);
402475d3a19aSMatthew G. Knepley     if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank);
402575d3a19aSMatthew G. Knepley     switch (refiner) {
402675d3a19aSMatthew G. Knepley     case 1:
402775d3a19aSMatthew G. Knepley       /* Simplicial 2D */
402875d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
402975d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
403075d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
403175d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
403275d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
403375d3a19aSMatthew G. Knepley         ++m;
403475d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
403575d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
403675d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
403775d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
403875d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
403975d3a19aSMatthew G. Knepley         ++m;
404075d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
404175d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
404275d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
404375d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
404475d3a19aSMatthew G. Knepley         }
404575d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
404675d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
404775d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
404875d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
404975d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
405075d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
405175d3a19aSMatthew G. Knepley         }
405275d3a19aSMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
405375d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*3     + r;
405475d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r;
405575d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
405675d3a19aSMatthew G. Knepley         }
405775d3a19aSMatthew G. Knepley       }
405875d3a19aSMatthew G. Knepley       break;
405975d3a19aSMatthew G. Knepley     case 2:
406075d3a19aSMatthew G. Knepley       /* Hex 2D */
406175d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
406275d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
406375d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
406475d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
406575d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
406675d3a19aSMatthew G. Knepley         ++m;
406775d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
406875d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
406975d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
407075d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
407175d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
407275d3a19aSMatthew G. Knepley         ++m;
407375d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
407475d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
407575d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
407675d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
407775d3a19aSMatthew G. Knepley         }
407875d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
4079455d6cd4SMatthew G. Knepley         /* Old cells add new cells, interior faces, and vertex */
408075d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
408175d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
408275d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
408375d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
408475d3a19aSMatthew G. Knepley         }
408575d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
408675d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*4     + r;
408775d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r;
408875d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
408975d3a19aSMatthew G. Knepley         }
4090455d6cd4SMatthew G. Knepley         for (r = 0; r < 1; ++r, ++m) {
4091455d6cd4SMatthew G. Knepley           localPointsNew[m]        = vStartNew     + (fEnd - fStart)                    + (p  - cStart)     + r;
4092455d6cd4SMatthew G. Knepley           remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]) + r;
4093455d6cd4SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
4094455d6cd4SMatthew G. Knepley         }
409575d3a19aSMatthew G. Knepley       }
409675d3a19aSMatthew G. Knepley       break;
409775d3a19aSMatthew G. Knepley     case 3:
409875d3a19aSMatthew G. Knepley       /* Hybrid simplicial 2D */
409975d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
410075d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
410175d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
410275d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
410375d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
410475d3a19aSMatthew G. Knepley         ++m;
410575d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fMax)) {
410675d3a19aSMatthew G. Knepley         /* Old interior faces add new faces and vertex */
410775d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
410875d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
410975d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
411075d3a19aSMatthew G. Knepley         ++m;
411175d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
411275d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
411375d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
411475d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
411575d3a19aSMatthew G. Knepley         }
411675d3a19aSMatthew G. Knepley       } else if ((p >= fMax) && (p < fEnd)) {
411775d3a19aSMatthew G. Knepley         /* Old hybrid faces stay the same */
411875d3a19aSMatthew G. Knepley         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - fMax);
411975d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
412075d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
412175d3a19aSMatthew G. Knepley         ++m;
412275d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cMax)) {
412375d3a19aSMatthew G. Knepley         /* Old interior cells add new cells and interior faces */
412475d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
412575d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
412675d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
412775d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
412875d3a19aSMatthew G. Knepley         }
412975d3a19aSMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
413075d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - cStart)*3     + r;
413175d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r;
413275d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
413375d3a19aSMatthew G. Knepley         }
413475d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cMax)) {
413575d3a19aSMatthew G. Knepley         /* Old hybrid cells add new cells and hybrid face */
413675d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
413775d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
413875d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
413975d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
414075d3a19aSMatthew G. Knepley         }
414175d3a19aSMatthew G. Knepley         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (cMax                            - cStart)*3     + (p  - cMax);
414275d3a19aSMatthew 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]);
414375d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
414475d3a19aSMatthew G. Knepley         ++m;
414575d3a19aSMatthew G. Knepley       }
414675d3a19aSMatthew G. Knepley       break;
4147b5da9499SMatthew G. Knepley     case 5:
4148b5da9499SMatthew G. Knepley       /* Simplicial 3D */
4149b5da9499SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
4150b5da9499SMatthew G. Knepley         /* Old vertices stay the same */
4151b5da9499SMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
4152b5da9499SMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
4153b5da9499SMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
4154b5da9499SMatthew G. Knepley         ++m;
415587fe6628SMatthew G. Knepley       } else if ((p >= eStart) && (p < eEnd)) {
4156b5da9499SMatthew G. Knepley         /* Old edges add new edges and vertex */
4157b5da9499SMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
4158b5da9499SMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
4159b5da9499SMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
4160b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
4161b5da9499SMatthew G. Knepley         }
4162b5da9499SMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
4163b5da9499SMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
4164b5da9499SMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
4165b5da9499SMatthew G. Knepley         ++m;
4166b5da9499SMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
4167b5da9499SMatthew G. Knepley         /* Old faces add new faces and face edges */
4168b5da9499SMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
4169b5da9499SMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
4170b5da9499SMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
4171b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
4172b5da9499SMatthew G. Knepley         }
4173b5da9499SMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
4174b5da9499SMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (p  - fStart)*3     + r;
4175b5da9499SMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + (rp - rfStart[n])*3 + r;
4176b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
4177b5da9499SMatthew G. Knepley         }
4178b5da9499SMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
4179b5da9499SMatthew G. Knepley         /* Old cells add new cells and interior faces and edges */
4180b5da9499SMatthew G. Knepley         for (r = 0; r < 8; ++r, ++m) {
4181b5da9499SMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
4182b5da9499SMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
4183b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
4184b5da9499SMatthew G. Knepley         }
4185b5da9499SMatthew G. Knepley         for (r = 0; r < 8; ++r, ++m) {
4186b5da9499SMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*4                    + (p  - cStart)*8     + r;
4187b5da9499SMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*8 + r;
4188b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
4189b5da9499SMatthew G. Knepley         }
4190b5da9499SMatthew G. Knepley         for (r = 0; r < 1; ++r, ++m) {
4191b5da9499SMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (fEnd - fStart)*3                    + (p  - cStart)*1     + r;
4192b5da9499SMatthew 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;
4193b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
4194b5da9499SMatthew G. Knepley         }
4195b5da9499SMatthew G. Knepley       }
4196b5da9499SMatthew G. Knepley       break;
41976ce3c06aSMatthew G. Knepley     case 7:
41986ce3c06aSMatthew G. Knepley       /* Hybrid Simplicial 3D */
41996ce3c06aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
42006ce3c06aSMatthew G. Knepley         /* Interior vertices stay the same */
42016ce3c06aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
42026ce3c06aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
42036ce3c06aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
42046ce3c06aSMatthew G. Knepley         ++m;
42056ce3c06aSMatthew G. Knepley       } else if ((p >= eStart) && (p < eMax)) {
42066ce3c06aSMatthew G. Knepley         /* Interior edges add new edges and vertex */
42076ce3c06aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
42086ce3c06aSMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
42096ce3c06aSMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
42106ce3c06aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
42116ce3c06aSMatthew G. Knepley         }
42126ce3c06aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
42136ce3c06aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
42146ce3c06aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
42156ce3c06aSMatthew G. Knepley         ++m;
42166ce3c06aSMatthew G. Knepley       } else if ((p >= eMax) && (p < eEnd)) {
42176ce3c06aSMatthew G. Knepley         /* Hybrid edges stay the same */
42186ce3c06aSMatthew G. Knepley         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (cMax                            - cStart)     + (p  - eMax);
42196ce3c06aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*3 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n]) + (rp - rdepthMaxOld[n*(depth+1)+1]);
42206ce3c06aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
42216ce3c06aSMatthew G. Knepley         ++m;
42226ce3c06aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fMax)) {
42236ce3c06aSMatthew G. Knepley         /* Interior faces add new faces and edges */
42246ce3c06aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
42256ce3c06aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
42266ce3c06aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
42276ce3c06aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
42286ce3c06aSMatthew G. Knepley         }
42296ce3c06aSMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
42306ce3c06aSMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (p  - fStart)*3     + r;
42316ce3c06aSMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*3 + r;
42326ce3c06aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
42336ce3c06aSMatthew G. Knepley         }
42346ce3c06aSMatthew G. Knepley       } else if ((p >= fMax) && (p < fEnd)) {
42356ce3c06aSMatthew G. Knepley         /* Hybrid faces add new faces and edges */
42366ce3c06aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
42376ce3c06aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (p  - fStart)*2     + r;
42386ce3c06aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rfStart[n])*2 + r;
42396ce3c06aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
42406ce3c06aSMatthew G. Knepley         }
42416ce3c06aSMatthew G. Knepley         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)     + (cMax                            - cStart)     + (fEnd                                          - fMax);
42426ce3c06aSMatthew G. Knepley         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n]) + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1]);
42436ce3c06aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
42446ce3c06aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cMax)) {
42456ce3c06aSMatthew G. Knepley         /* Interior cells add new cells, faces, and edges */
42466ce3c06aSMatthew G. Knepley         for (r = 0; r < 8; ++r, ++m) {
42476ce3c06aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
42486ce3c06aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
42496ce3c06aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
42506ce3c06aSMatthew G. Knepley         }
42516ce3c06aSMatthew G. Knepley         for (r = 0; r < 8; ++r, ++m) {
42526ce3c06aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (p  - cStart)*8     + r;
42536ce3c06aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*8 + r;
42546ce3c06aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
42556ce3c06aSMatthew G. Knepley         }
42566ce3c06aSMatthew G. Knepley         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (p  - cStart)*1     + r;
42576ce3c06aSMatthew G. Knepley         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*3 + (rp - rcStart[n])*1 + r;
42586ce3c06aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
42596ce3c06aSMatthew G. Knepley       } else if ((p >= cMax) && (p < cEnd)) {
42606ce3c06aSMatthew G. Knepley         /* Hybrid cells add new cells and faces */
42616ce3c06aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
42626ce3c06aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (cMax                            - cStart)*8     + (p  - cMax)*4                            + r;
42636ce3c06aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
42646ce3c06aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
42656ce3c06aSMatthew G. Knepley         }
42666ce3c06aSMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
42676ce3c06aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (fEnd                                          - fMax)*4                              + (p  - cMax)*3                            + r;
42686ce3c06aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1])*4 + (rp - rdepthMaxOld[n*(depth+1)+depth])*3 + r;
42696ce3c06aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
42706ce3c06aSMatthew G. Knepley         }
42716ce3c06aSMatthew G. Knepley       }
42726ce3c06aSMatthew G. Knepley       break;
42732eabf88fSMatthew G. Knepley     case 6:
42742eabf88fSMatthew G. Knepley       /* Hex 3D */
42752eabf88fSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
42762eabf88fSMatthew G. Knepley         /* Old vertices stay the same */
42772eabf88fSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
42782eabf88fSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
42792eabf88fSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
42802eabf88fSMatthew G. Knepley         ++m;
42812eabf88fSMatthew G. Knepley       } else if ((p >= eStart) && (p < eEnd)) {
42822eabf88fSMatthew G. Knepley         /* Old edges add new edges and vertex */
42832eabf88fSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
42842eabf88fSMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
42852eabf88fSMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
42862eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
42872eabf88fSMatthew G. Knepley         }
42882eabf88fSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
42892eabf88fSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
42902eabf88fSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
42912eabf88fSMatthew G. Knepley         ++m;
42922eabf88fSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
42932eabf88fSMatthew G. Knepley         /* Old faces add new faces, edges, and vertex */
42942eabf88fSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
42952eabf88fSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
42962eabf88fSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
42972eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
42982eabf88fSMatthew G. Knepley         }
42992eabf88fSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
43002eabf88fSMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (p  - fStart)*4     + r;
43012eabf88fSMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + (rp - rfStart[n])*4 + r;
43022eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
43032eabf88fSMatthew G. Knepley         }
43042eabf88fSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (eEnd - eStart)              + (p  - fStart);
43052eabf88fSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+1] + (rp - rfStart[n]);
43062eabf88fSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
43072eabf88fSMatthew G. Knepley         ++m;
43082eabf88fSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
43092eabf88fSMatthew G. Knepley         /* Old cells add new cells, faces, edges, and vertex */
43102eabf88fSMatthew G. Knepley         for (r = 0; r < 8; ++r, ++m) {
43112eabf88fSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
43122eabf88fSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
43132eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
43142eabf88fSMatthew G. Knepley         }
43152eabf88fSMatthew G. Knepley         for (r = 0; r < 12; ++r, ++m) {
43162eabf88fSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*4                    + (p  - cStart)*12     + r;
43172eabf88fSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*12 + r;
43182eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
43192eabf88fSMatthew G. Knepley         }
43202eabf88fSMatthew G. Knepley         for (r = 0; r < 6; ++r, ++m) {
43212eabf88fSMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (fEnd - fStart)*4                    + (p  - cStart)*6     + r;
43222eabf88fSMatthew 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;
43232eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
43242eabf88fSMatthew G. Knepley         }
43252eabf88fSMatthew G. Knepley         for (r = 0; r < 1; ++r, ++m) {
43262eabf88fSMatthew G. Knepley           localPointsNew[m]        = vStartNew     + (eEnd - eStart)              + (fEnd - fStart)                    + (p  - cStart)     + r;
43272eabf88fSMatthew G. Knepley           remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+1] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]) + r;
43282eabf88fSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
43292eabf88fSMatthew G. Knepley         }
43302eabf88fSMatthew G. Knepley       }
43312eabf88fSMatthew G. Knepley       break;
433275d3a19aSMatthew G. Knepley     default:
433375d3a19aSMatthew G. Knepley       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
433475d3a19aSMatthew G. Knepley     }
433575d3a19aSMatthew G. Knepley   }
433675d3a19aSMatthew G. Knepley   ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr);
433775d3a19aSMatthew G. Knepley   ierr = ISDestroy(&processRanks);CHKERRQ(ierr);
433875d3a19aSMatthew G. Knepley   ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
433975d3a19aSMatthew G. Knepley   ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr);
434006a0ba2dSMatthew G. Knepley   ierr = PetscFree7(depthSizeOld,rdepthSizeOld,rdepthMaxOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr);
434175d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
434275d3a19aSMatthew G. Knepley }
434375d3a19aSMatthew G. Knepley 
434475d3a19aSMatthew G. Knepley #undef __FUNCT__
434575d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerCreateLabels"
434675d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
434775d3a19aSMatthew G. Knepley {
434875d3a19aSMatthew G. Knepley   PetscInt       numLabels, l;
4349*c3a233c8SMatthew G. Knepley   PetscInt       depth, newp, cStart, cStartNew = 0, cEnd, cMax, vStart, vStartNew = 0, vEnd, vMax, fStart, fStartNew = 0, fEnd, fMax, eStart, eStartNew = 0, eEnd, eMax, r;
435075d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
435175d3a19aSMatthew G. Knepley 
435275d3a19aSMatthew G. Knepley   PetscFunctionBegin;
435375d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
435475d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
435575d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
435675d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
4357d963de37SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
43583478d7aaSMatthew G. Knepley   if (refiner) {ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);}
435975d3a19aSMatthew G. Knepley   ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
436075d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
436175d3a19aSMatthew G. Knepley   switch (refiner) {
43623478d7aaSMatthew G. Knepley   case 0: break;
436358b8852aSMatthew G. Knepley   case 7:
436458b8852aSMatthew G. Knepley   case 8:
436558b8852aSMatthew G. Knepley     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
436675d3a19aSMatthew G. Knepley   case 3:
436758b8852aSMatthew G. Knepley   case 4:
436875d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
436975d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
437075d3a19aSMatthew G. Knepley   }
437175d3a19aSMatthew G. Knepley   for (l = 0; l < numLabels; ++l) {
437275d3a19aSMatthew G. Knepley     DMLabel         label, labelNew;
437375d3a19aSMatthew G. Knepley     const char     *lname;
437475d3a19aSMatthew G. Knepley     PetscBool       isDepth;
437575d3a19aSMatthew G. Knepley     IS              valueIS;
437675d3a19aSMatthew G. Knepley     const PetscInt *values;
437775d3a19aSMatthew G. Knepley     PetscInt        numValues, val;
437875d3a19aSMatthew G. Knepley 
437975d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr);
438075d3a19aSMatthew G. Knepley     ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr);
438175d3a19aSMatthew G. Knepley     if (isDepth) continue;
438275d3a19aSMatthew G. Knepley     ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr);
438375d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr);
438475d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr);
438575d3a19aSMatthew G. Knepley     ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
438675d3a19aSMatthew G. Knepley     ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr);
438775d3a19aSMatthew G. Knepley     ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
438875d3a19aSMatthew G. Knepley     for (val = 0; val < numValues; ++val) {
438975d3a19aSMatthew G. Knepley       IS              pointIS;
439075d3a19aSMatthew G. Knepley       const PetscInt *points;
439175d3a19aSMatthew G. Knepley       PetscInt        numPoints, n;
439275d3a19aSMatthew G. Knepley 
439375d3a19aSMatthew G. Knepley       ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr);
439475d3a19aSMatthew G. Knepley       ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
439575d3a19aSMatthew G. Knepley       ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
439675d3a19aSMatthew G. Knepley       for (n = 0; n < numPoints; ++n) {
439775d3a19aSMatthew G. Knepley         const PetscInt p = points[n];
439875d3a19aSMatthew G. Knepley         switch (refiner) {
439975d3a19aSMatthew G. Knepley         case 1:
440075d3a19aSMatthew G. Knepley           /* Simplicial 2D */
440175d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
440275d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
440375d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
440475d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
440575d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
440675d3a19aSMatthew G. Knepley             /* Old faces add new faces and vertex */
440775d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
440875d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
440975d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
441075d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
441175d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
441275d3a19aSMatthew G. Knepley             }
441375d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
441475d3a19aSMatthew G. Knepley             /* Old cells add new cells and interior faces */
441575d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
441675d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
441775d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
441875d3a19aSMatthew G. Knepley             }
441975d3a19aSMatthew G. Knepley             for (r = 0; r < 3; ++r) {
442075d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
442175d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
442275d3a19aSMatthew G. Knepley             }
442375d3a19aSMatthew G. Knepley           }
442475d3a19aSMatthew G. Knepley           break;
442575d3a19aSMatthew G. Knepley         case 2:
442675d3a19aSMatthew G. Knepley           /* Hex 2D */
442775d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
442875d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
442975d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
443075d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
443175d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
443275d3a19aSMatthew G. Knepley             /* Old faces add new faces and vertex */
443375d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
443475d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
443575d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
443675d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
443775d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
443875d3a19aSMatthew G. Knepley             }
443975d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
444075d3a19aSMatthew G. Knepley             /* Old cells add new cells and interior faces and vertex */
444175d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
444275d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
444375d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
444475d3a19aSMatthew G. Knepley             }
444575d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
444675d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
444775d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
444875d3a19aSMatthew G. Knepley             }
444975d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
445075d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
445175d3a19aSMatthew G. Knepley           }
445275d3a19aSMatthew G. Knepley           break;
445375d3a19aSMatthew G. Knepley         case 3:
445475d3a19aSMatthew G. Knepley           /* Hybrid simplicial 2D */
445575d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
445675d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
445775d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
445875d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
445975d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fMax)) {
446075d3a19aSMatthew G. Knepley             /* Old interior faces add new faces and vertex */
446175d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
446275d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
446375d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
446475d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
446575d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
446675d3a19aSMatthew G. Knepley             }
446775d3a19aSMatthew G. Knepley           } else if ((p >= fMax) && (p < fEnd)) {
446875d3a19aSMatthew G. Knepley             /* Old hybrid faces stay the same */
446975d3a19aSMatthew G. Knepley             newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
447075d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
447175d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cMax)) {
447275d3a19aSMatthew G. Knepley             /* Old interior cells add new cells and interior faces */
447375d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
447475d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
447575d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
447675d3a19aSMatthew G. Knepley             }
447775d3a19aSMatthew G. Knepley             for (r = 0; r < 3; ++r) {
447875d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
447975d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
448075d3a19aSMatthew G. Knepley             }
448175d3a19aSMatthew G. Knepley           } else if ((p >= cMax) && (p < cEnd)) {
448275d3a19aSMatthew G. Knepley             /* Old hybrid cells add new cells and hybrid face */
448375d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
448475d3a19aSMatthew G. Knepley               newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
448575d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
448675d3a19aSMatthew G. Knepley             }
448775d3a19aSMatthew G. Knepley             newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
448875d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
448975d3a19aSMatthew G. Knepley           }
449075d3a19aSMatthew G. Knepley           break;
4491b5da9499SMatthew G. Knepley         case 5:
4492b5da9499SMatthew G. Knepley           /* Simplicial 3D */
4493b5da9499SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
4494b5da9499SMatthew G. Knepley             /* Old vertices stay the same */
4495b5da9499SMatthew G. Knepley             newp = vStartNew + (p - vStart);
4496b5da9499SMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
4497b5da9499SMatthew G. Knepley           } else if ((p >= eStart) && (p < eEnd)) {
4498b5da9499SMatthew G. Knepley             /* Old edges add new edges and vertex */
4499b5da9499SMatthew G. Knepley             for (r = 0; r < 2; ++r) {
4500b5da9499SMatthew G. Knepley               newp = eStartNew + (p - eStart)*2 + r;
4501b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
4502b5da9499SMatthew G. Knepley             }
4503b5da9499SMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - eStart);
4504b5da9499SMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
4505b5da9499SMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
4506b5da9499SMatthew G. Knepley             /* Old faces add new faces and edges */
4507b5da9499SMatthew G. Knepley             for (r = 0; r < 4; ++r) {
4508b5da9499SMatthew G. Knepley               newp = fStartNew + (p - fStart)*4 + r;
4509b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
4510b5da9499SMatthew G. Knepley             }
4511b5da9499SMatthew G. Knepley             for (r = 0; r < 3; ++r) {
4512b5da9499SMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
4513b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
4514b5da9499SMatthew G. Knepley             }
4515b5da9499SMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
4516b5da9499SMatthew G. Knepley             /* Old cells add new cells and interior faces and edges */
4517b5da9499SMatthew G. Knepley             for (r = 0; r < 8; ++r) {
4518b5da9499SMatthew G. Knepley               newp = cStartNew + (p - cStart)*8 + r;
4519b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
4520b5da9499SMatthew G. Knepley             }
4521b5da9499SMatthew G. Knepley             for (r = 0; r < 8; ++r) {
4522b5da9499SMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*8 + r;
4523b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
4524b5da9499SMatthew G. Knepley             }
4525b5da9499SMatthew G. Knepley             for (r = 0; r < 1; ++r) {
4526b5da9499SMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*1 + r;
4527b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
4528b5da9499SMatthew G. Knepley             }
4529b5da9499SMatthew G. Knepley           }
4530b5da9499SMatthew G. Knepley           break;
45316ce3c06aSMatthew G. Knepley         case 7:
45326ce3c06aSMatthew G. Knepley           /* Hybrid Simplicial 3D */
45336ce3c06aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
45346ce3c06aSMatthew G. Knepley             /* Interior vertices stay the same */
45356ce3c06aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
45366ce3c06aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
45376ce3c06aSMatthew G. Knepley           } else if ((p >= eStart) && (p < eMax)) {
45386ce3c06aSMatthew G. Knepley             /* Interior edges add new edges and vertex */
45396ce3c06aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
45406ce3c06aSMatthew G. Knepley               newp = eStartNew + (p - eStart)*2 + r;
45416ce3c06aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
45426ce3c06aSMatthew G. Knepley             }
45436ce3c06aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - eStart);
45446ce3c06aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
45456ce3c06aSMatthew G. Knepley           } else if ((p >= eMax) && (p < eEnd)) {
45466ce3c06aSMatthew G. Knepley             /* Hybrid edges stay the same */
45476ce3c06aSMatthew G. Knepley             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - eMax);
45486ce3c06aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
45496ce3c06aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fMax)) {
45506ce3c06aSMatthew G. Knepley             /* Interior faces add new faces and edges */
45516ce3c06aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
45526ce3c06aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*4 + r;
45536ce3c06aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
45546ce3c06aSMatthew G. Knepley             }
45556ce3c06aSMatthew G. Knepley             for (r = 0; r < 3; ++r) {
45566ce3c06aSMatthew G. Knepley               newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
45576ce3c06aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
45586ce3c06aSMatthew G. Knepley             }
45596ce3c06aSMatthew G. Knepley           } else if ((p >= fMax) && (p < fEnd)) {
45606ce3c06aSMatthew G. Knepley             /* Hybrid faces add new faces and edges */
45616ce3c06aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
45626ce3c06aSMatthew G. Knepley               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (p - fMax)*2 + r;
45636ce3c06aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
45646ce3c06aSMatthew G. Knepley             }
45656ce3c06aSMatthew G. Knepley             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - fMax);
45666ce3c06aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
45676ce3c06aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cMax)) {
45686ce3c06aSMatthew G. Knepley             /* Interior cells add new cells, faces, and edges */
45696ce3c06aSMatthew G. Knepley             for (r = 0; r < 8; ++r) {
45706ce3c06aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*8 + r;
45716ce3c06aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
45726ce3c06aSMatthew G. Knepley             }
45736ce3c06aSMatthew G. Knepley             for (r = 0; r < 8; ++r) {
45746ce3c06aSMatthew G. Knepley               newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*8 + r;
45756ce3c06aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
45766ce3c06aSMatthew G. Knepley             }
45776ce3c06aSMatthew G. Knepley             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart);
45786ce3c06aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
457958b8852aSMatthew G. Knepley           } else if ((p >= cMax) && (p < cEnd)) {
45806ce3c06aSMatthew G. Knepley             /* Hybrid cells add new cells and faces */
45816ce3c06aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
45826ce3c06aSMatthew G. Knepley               newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
45836ce3c06aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
45846ce3c06aSMatthew G. Knepley             }
45856ce3c06aSMatthew G. Knepley             for (r = 0; r < 3; ++r) {
45866ce3c06aSMatthew G. Knepley               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
45876ce3c06aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
45886ce3c06aSMatthew G. Knepley             }
45896ce3c06aSMatthew G. Knepley           }
45906ce3c06aSMatthew G. Knepley           break;
45912eabf88fSMatthew G. Knepley         case 6:
45922eabf88fSMatthew G. Knepley           /* Hex 3D */
45932eabf88fSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
45942eabf88fSMatthew G. Knepley             /* Old vertices stay the same */
45952eabf88fSMatthew G. Knepley             newp = vStartNew + (p - vStart);
45962eabf88fSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
459719d7d790SMatthew G. Knepley           } else if ((p >= eStart) && (p < eEnd)) {
45982eabf88fSMatthew G. Knepley             /* Old edges add new edges and vertex */
45992eabf88fSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
46002eabf88fSMatthew G. Knepley               newp = eStartNew + (p - eStart)*2 + r;
46012eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
46022eabf88fSMatthew G. Knepley             }
46032eabf88fSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - eStart);
46042eabf88fSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
46052eabf88fSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
46062eabf88fSMatthew G. Knepley             /* Old faces add new faces, edges, and vertex */
46072eabf88fSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
46082eabf88fSMatthew G. Knepley               newp = fStartNew + (p - fStart)*4 + r;
46092eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
46102eabf88fSMatthew G. Knepley             }
46112eabf88fSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
46122eabf88fSMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*4 + r;
46132eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
46142eabf88fSMatthew G. Knepley             }
46152eabf88fSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (p - fStart);
46162eabf88fSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
46172eabf88fSMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
46182eabf88fSMatthew G. Knepley             /* Old cells add new cells, faces, edges, and vertex */
46192eabf88fSMatthew G. Knepley             for (r = 0; r < 8; ++r) {
46202eabf88fSMatthew G. Knepley               newp = cStartNew + (p - cStart)*8 + r;
46212eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
46222eabf88fSMatthew G. Knepley             }
46232eabf88fSMatthew G. Knepley             for (r = 0; r < 12; ++r) {
46242eabf88fSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*12 + r;
46252eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
46262eabf88fSMatthew G. Knepley             }
46272eabf88fSMatthew G. Knepley             for (r = 0; r < 6; ++r) {
46282eabf88fSMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (p - cStart)*6 + r;
46292eabf88fSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
46302eabf88fSMatthew G. Knepley             }
46312eabf88fSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (p - cStart);
46322eabf88fSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
46332eabf88fSMatthew G. Knepley           }
46342eabf88fSMatthew G. Knepley           break;
463575d3a19aSMatthew G. Knepley         default:
463675d3a19aSMatthew G. Knepley           SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
463775d3a19aSMatthew G. Knepley         }
463875d3a19aSMatthew G. Knepley       }
463975d3a19aSMatthew G. Knepley       ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
464075d3a19aSMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
464175d3a19aSMatthew G. Knepley     }
464275d3a19aSMatthew G. Knepley     ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
464375d3a19aSMatthew G. Knepley     ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
464475d3a19aSMatthew G. Knepley     if (0) {
464575d3a19aSMatthew G. Knepley       ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr);
464675d3a19aSMatthew G. Knepley       ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
464775d3a19aSMatthew G. Knepley       ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
464875d3a19aSMatthew G. Knepley     }
464975d3a19aSMatthew G. Knepley   }
465075d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
465175d3a19aSMatthew G. Knepley }
465275d3a19aSMatthew G. Knepley 
465375d3a19aSMatthew G. Knepley #undef __FUNCT__
4654509c9b89SMatthew G. Knepley #define __FUNCT__ "DMPlexRefineUniform_Internal"
465575d3a19aSMatthew G. Knepley /* This will only work for interpolated meshes */
4656509c9b89SMatthew G. Knepley PetscErrorCode DMPlexRefineUniform_Internal(DM dm, CellRefiner cellRefiner, DM *dmRefined)
465775d3a19aSMatthew G. Knepley {
465875d3a19aSMatthew G. Knepley   DM             rdm;
465975d3a19aSMatthew G. Knepley   PetscInt      *depthSize;
466075d3a19aSMatthew G. Knepley   PetscInt       dim, depth = 0, d, pStart = 0, pEnd = 0;
466175d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
466275d3a19aSMatthew G. Knepley 
466375d3a19aSMatthew G. Knepley   PetscFunctionBegin;
466475d3a19aSMatthew G. Knepley   ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr);
466575d3a19aSMatthew G. Knepley   ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr);
466675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
466775d3a19aSMatthew G. Knepley   ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr);
466875d3a19aSMatthew G. Knepley   /* Calculate number of new points of each depth */
466975d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
467075d3a19aSMatthew G. Knepley   ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr);
467175d3a19aSMatthew G. Knepley   ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr);
467275d3a19aSMatthew G. Knepley   ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr);
467375d3a19aSMatthew G. Knepley   /* Step 1: Set chart */
467475d3a19aSMatthew G. Knepley   for (d = 0; d <= depth; ++d) pEnd += depthSize[d];
467575d3a19aSMatthew G. Knepley   ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr);
467675d3a19aSMatthew G. Knepley   /* Step 2: Set cone/support sizes */
467775d3a19aSMatthew G. Knepley   ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
467875d3a19aSMatthew G. Knepley   /* Step 3: Setup refined DM */
467975d3a19aSMatthew G. Knepley   ierr = DMSetUp(rdm);CHKERRQ(ierr);
468075d3a19aSMatthew G. Knepley   /* Step 4: Set cones and supports */
468175d3a19aSMatthew G. Knepley   ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
468275d3a19aSMatthew G. Knepley   /* Step 5: Stratify */
468375d3a19aSMatthew G. Knepley   ierr = DMPlexStratify(rdm);CHKERRQ(ierr);
468475d3a19aSMatthew G. Knepley   /* Step 6: Set coordinates for vertices */
468575d3a19aSMatthew G. Knepley   ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
468675d3a19aSMatthew G. Knepley   /* Step 7: Create pointSF */
468775d3a19aSMatthew G. Knepley   ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
468875d3a19aSMatthew G. Knepley   /* Step 8: Create labels */
468975d3a19aSMatthew G. Knepley   ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
469075d3a19aSMatthew G. Knepley   ierr = PetscFree(depthSize);CHKERRQ(ierr);
469175d3a19aSMatthew G. Knepley 
469275d3a19aSMatthew G. Knepley   *dmRefined = rdm;
469375d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
469475d3a19aSMatthew G. Knepley }
469575d3a19aSMatthew G. Knepley 
469675d3a19aSMatthew G. Knepley #undef __FUNCT__
469775d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexSetRefinementUniform"
469875d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
469975d3a19aSMatthew G. Knepley {
470075d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
470175d3a19aSMatthew G. Knepley 
470275d3a19aSMatthew G. Knepley   PetscFunctionBegin;
470375d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
470475d3a19aSMatthew G. Knepley   mesh->refinementUniform = refinementUniform;
470575d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
470675d3a19aSMatthew G. Knepley }
470775d3a19aSMatthew G. Knepley 
470875d3a19aSMatthew G. Knepley #undef __FUNCT__
470975d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexGetRefinementUniform"
471075d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
471175d3a19aSMatthew G. Knepley {
471275d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
471375d3a19aSMatthew G. Knepley 
471475d3a19aSMatthew G. Knepley   PetscFunctionBegin;
471575d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
471675d3a19aSMatthew G. Knepley   PetscValidPointer(refinementUniform,  2);
471775d3a19aSMatthew G. Knepley   *refinementUniform = mesh->refinementUniform;
471875d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
471975d3a19aSMatthew G. Knepley }
472075d3a19aSMatthew G. Knepley 
472175d3a19aSMatthew G. Knepley #undef __FUNCT__
472275d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexSetRefinementLimit"
472375d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
472475d3a19aSMatthew G. Knepley {
472575d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
472675d3a19aSMatthew G. Knepley 
472775d3a19aSMatthew G. Knepley   PetscFunctionBegin;
472875d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
472975d3a19aSMatthew G. Knepley   mesh->refinementLimit = refinementLimit;
473075d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
473175d3a19aSMatthew G. Knepley }
473275d3a19aSMatthew G. Knepley 
473375d3a19aSMatthew G. Knepley #undef __FUNCT__
473475d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexGetRefinementLimit"
473575d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
473675d3a19aSMatthew G. Knepley {
473775d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
473875d3a19aSMatthew G. Knepley 
473975d3a19aSMatthew G. Knepley   PetscFunctionBegin;
474075d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
474175d3a19aSMatthew G. Knepley   PetscValidPointer(refinementLimit,  2);
474275d3a19aSMatthew G. Knepley   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
474375d3a19aSMatthew G. Knepley   *refinementLimit = mesh->refinementLimit;
474475d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
474575d3a19aSMatthew G. Knepley }
474675d3a19aSMatthew G. Knepley 
474775d3a19aSMatthew G. Knepley #undef __FUNCT__
4748509c9b89SMatthew G. Knepley #define __FUNCT__ "DMPlexGetCellRefiner_Internal"
4749509c9b89SMatthew G. Knepley PetscErrorCode DMPlexGetCellRefiner_Internal(DM dm, CellRefiner *cellRefiner)
475075d3a19aSMatthew G. Knepley {
47513478d7aaSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, coneSize, cMax;
475275d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
475375d3a19aSMatthew G. Knepley 
475475d3a19aSMatthew G. Knepley   PetscFunctionBegin;
475575d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
47563478d7aaSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
47573478d7aaSMatthew G. Knepley   if (cEnd <= cStart) {*cellRefiner = 0; PetscFunctionReturn(0);}
475875d3a19aSMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr);
475975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr);
476075d3a19aSMatthew G. Knepley   switch (dim) {
476175d3a19aSMatthew G. Knepley   case 2:
476275d3a19aSMatthew G. Knepley     switch (coneSize) {
476375d3a19aSMatthew G. Knepley     case 3:
476475d3a19aSMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 3; /* Hybrid */
476575d3a19aSMatthew G. Knepley       else *cellRefiner = 1; /* Triangular */
476675d3a19aSMatthew G. Knepley       break;
476775d3a19aSMatthew G. Knepley     case 4:
476875d3a19aSMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 4; /* Hybrid */
476975d3a19aSMatthew G. Knepley       else *cellRefiner = 2; /* Quadrilateral */
477075d3a19aSMatthew G. Knepley       break;
477175d3a19aSMatthew G. Knepley     default:
477275d3a19aSMatthew G. Knepley       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
477375d3a19aSMatthew G. Knepley     }
477475d3a19aSMatthew G. Knepley     break;
4775b5da9499SMatthew G. Knepley   case 3:
4776b5da9499SMatthew G. Knepley     switch (coneSize) {
4777b5da9499SMatthew G. Knepley     case 4:
4778b5da9499SMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 7; /* Hybrid */
4779b5da9499SMatthew G. Knepley       else *cellRefiner = 5; /* Tetrahedral */
4780b5da9499SMatthew G. Knepley       break;
47812eabf88fSMatthew G. Knepley     case 6:
47822eabf88fSMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 8; /* Hybrid */
47832eabf88fSMatthew G. Knepley       else *cellRefiner = 6; /* hexahedral */
47842eabf88fSMatthew G. Knepley       break;
4785b5da9499SMatthew G. Knepley     default:
4786b5da9499SMatthew G. Knepley       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
4787b5da9499SMatthew G. Knepley     }
4788b5da9499SMatthew G. Knepley     break;
478975d3a19aSMatthew G. Knepley   default:
479075d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim);
479175d3a19aSMatthew G. Knepley   }
479275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
479375d3a19aSMatthew G. Knepley }
4794