xref: /petsc/src/dm/impls/plex/plexrefine.c (revision c5354d4ac2d38db92147d586b7a406d64f591021)
1 #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2 #include <petscsf.h>
3 
4 const char * const CellRefiners[] = {"NOOP", "SIMPLEX_1D", "SIMPLEX_2D", "HYBRID_SIMPLEX_2D", "SIMPLEX_TO_HEX_2D", "HYBRID_SIMPLEX_TO_HEX_2D", "HEX_2D", "HYBRID_HEX_2D",
5                                      "SIMPLEX_3D", "HYBRID_SIMPLEX_3D", "SIMPLEX_TO_HEX_3D", "HYBRID_SIMPLEX_TO_HEX_3D", "HEX_3D", "HYBRID_HEX_3D", "CellRefiners", "REFINER_", 0};
6 
7 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart)
8 {
9   PetscFunctionBegin;
10   if (cStart) *cStart = 0;
11   if (vStart) *vStart = depth < 0 ? 0 : depthSize[depth];
12   if (fStart) *fStart = depth < 0 ? 0 : depthSize[depth] + depthSize[0];
13   if (eStart) *eStart = depth < 0 ? 0 : depthSize[depth] + depthSize[0] + depthSize[depth-1];
14   PetscFunctionReturn(0);
15 }
16 
17 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd)
18 {
19   PetscFunctionBegin;
20   if (cEnd) *cEnd = depth < 0 ? 0 : depthSize[depth];
21   if (vEnd) *vEnd = depth < 0 ? 0 : depthSize[depth] + depthSize[0];
22   if (fEnd) *fEnd = depth < 0 ? 0 : depthSize[depth] + depthSize[0] + depthSize[depth-1];
23   if (eEnd) *eEnd = depth < 0 ? 0 : depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1];
24   PetscFunctionReturn(0);
25 }
26 
27 /* Gets the affine map from the original cell to each subcell */
28 PetscErrorCode CellRefinerGetAffineTransforms_Internal(CellRefiner refiner, PetscInt *numSubcells, PetscReal *v0[], PetscReal *jac[], PetscReal *invjac[])
29 {
30   PetscReal     *v = NULL, *j = NULL, *invj = NULL, detJ;
31   PetscInt       dim, s;
32   PetscErrorCode ierr;
33 
34   PetscFunctionBegin;
35   switch (refiner) {
36   case REFINER_NOOP: break;
37   case REFINER_SIMPLEX_2D:
38     /*
39      2
40      |\
41      | \
42      |  \
43      |   \
44      | C  \
45      |     \
46      |      \
47      2---1---1
48      |\  D  / \
49      | 2   0   \
50      |A \ /  B  \
51      0---0-------1
52      */
53     dim = 2;
54     if (numSubcells) *numSubcells = 4;
55     if (v0) {
56       ierr = PetscMalloc3(4*dim,&v,4*dim*dim,&j,4*dim*dim,&invj);CHKERRQ(ierr);
57       /* A */
58       v[0+0] = -1.0; v[0+1] = -1.0;
59       j[0+0] =  0.5; j[0+1] =  0.0;
60       j[0+2] =  0.0; j[0+3] =  0.5;
61       /* B */
62       v[2+0] =  0.0; v[2+1] = -1.0;
63       j[4+0] =  0.5; j[4+1] =  0.0;
64       j[4+2] =  0.0; j[4+3] =  0.5;
65       /* C */
66       v[4+0] = -1.0; v[4+1] =  0.0;
67       j[8+0] =  0.5; j[8+1] =  0.0;
68       j[8+2] =  0.0; j[8+3] =  0.5;
69       /* D */
70       v[6+0]  =  0.0; v[6+1]  = -1.0;
71       j[12+0] =  0.0; j[12+1] = -0.5;
72       j[12+2] =  0.5; j[12+3] =  0.5;
73       for (s = 0; s < 4; ++s) {
74         DMPlex_Det2D_Internal(&detJ, &j[s*dim*dim]);
75         DMPlex_Invert2D_Internal(&invj[s*dim*dim], &j[s*dim*dim], detJ);
76       }
77     }
78     break;
79   case REFINER_HEX_2D:
80     /*
81      3---------2---------2
82      |         |         |
83      |    D    2    C    |
84      |         |         |
85      3----3----0----1----1
86      |         |         |
87      |    A    0    B    |
88      |         |         |
89      0---------0---------1
90      */
91     dim = 2;
92     if (numSubcells) *numSubcells = 4;
93     if (v0) {
94       ierr = PetscMalloc3(4*dim,&v,4*dim*dim,&j,4*dim*dim,&invj);CHKERRQ(ierr);
95       /* A */
96       v[0+0] = -1.0; v[0+1] = -1.0;
97       j[0+0] =  0.5; j[0+1] =  0.0;
98       j[0+2] =  0.0; j[0+3] =  0.5;
99       /* B */
100       v[2+0] =  0.0; v[2+1] = -1.0;
101       j[4+0] =  0.5; j[4+1] =  0.0;
102       j[4+2] =  0.0; j[4+3] =  0.5;
103       /* C */
104       v[4+0] =  0.0; v[4+1] =  0.0;
105       j[8+0] =  0.5; j[8+1] =  0.0;
106       j[8+2] =  0.0; j[8+3] =  0.5;
107       /* D */
108       v[6+0]  = -1.0; v[6+1]  =  0.0;
109       j[12+0] =  0.5; j[12+1] =  0.0;
110       j[12+2] =  0.0; j[12+3] =  0.5;
111       for (s = 0; s < 4; ++s) {
112         DMPlex_Det2D_Internal(&detJ, &j[s*dim*dim]);
113         DMPlex_Invert2D_Internal(&invj[s*dim*dim], &j[s*dim*dim], detJ);
114       }
115     }
116     break;
117   case REFINER_HEX_3D:
118     /*
119      Bottom (viewed from top)    Top
120      1---------2---------2       7---------2---------6
121      |         |         |       |         |         |
122      |    B    2    C    |       |    H    2    G    |
123      |         |         |       |         |         |
124      3----3----0----1----1       3----3----0----1----1
125      |         |         |       |         |         |
126      |    A    0    D    |       |    E    0    F    |
127      |         |         |       |         |         |
128      0---------0---------3       4---------0---------5
129      */
130     break;
131     dim = 3;
132     if (numSubcells) *numSubcells = 8;
133     if (v0) {
134       ierr = PetscMalloc3(4*dim,&v,4*dim*dim,&j,4*dim*dim,&invj);CHKERRQ(ierr);
135       /* A */
136       v[0+0] = -1.0; v[0+1] = -1.0; v[0+2] = -1.0;
137       j[0+0] =  0.5; j[0+1] =  0.0; j[0+2] =  0.0;
138       j[0+3] =  0.0; j[0+4] =  0.5; j[0+5] =  0.0;
139       j[0+6] =  0.0; j[0+7] =  0.0; j[0+8] =  0.5;
140       /* B */
141       v[3+0] = -1.0; v[3+1] =  0.0; v[3+2] = -1.0;
142       j[9+0] =  0.5; j[9+1] =  0.0; j[9+2] =  0.0;
143       j[9+3] =  0.0; j[9+4] =  0.5; j[9+5] =  0.0;
144       j[9+6] =  0.0; j[9+7] =  0.0; j[9+8] =  0.5;
145       /* C */
146       v[6+0] =  0.0; v[6+1] =  0.0; v[6+2] = -1.0;
147       j[18+0] = 0.5; j[18+1] = 0.0; j[18+2] = 0.0;
148       j[18+3] = 0.0; j[18+4] = 0.5; j[18+5] = 0.0;
149       j[18+6] = 0.0; j[18+7] = 0.0; j[18+8] = 0.5;
150       /* D */
151       v[9+0] =  0.0; v[9+1] = -1.0; v[9+2] = -1.0;
152       j[27+0] = 0.5; j[27+1] = 0.0; j[27+2] = 0.0;
153       j[27+3] = 0.0; j[27+4] = 0.5; j[27+5] = 0.0;
154       j[27+6] = 0.0; j[27+7] = 0.0; j[27+8] = 0.5;
155       /* E */
156       v[12+0] = -1.0; v[12+1] = -1.0; v[12+2] =  0.0;
157       j[36+0] =  0.5; j[36+1] =  0.0; j[36+2] =  0.0;
158       j[36+3] =  0.0; j[36+4] =  0.5; j[36+5] =  0.0;
159       j[36+6] =  0.0; j[36+7] =  0.0; j[36+8] =  0.5;
160       /* F */
161       v[15+0] =  0.0; v[15+1] = -1.0; v[15+2] =  0.0;
162       j[45+0] =  0.5; j[45+1] =  0.0; j[45+2] =  0.0;
163       j[45+3] =  0.0; j[45+4] =  0.5; j[45+5] =  0.0;
164       j[45+6] =  0.0; j[45+7] =  0.0; j[45+8] =  0.5;
165       /* G */
166       v[18+0] =  0.0; v[18+1] =  0.0; v[18+2] =  0.0;
167       j[54+0] =  0.5; j[54+1] =  0.0; j[54+2] =  0.0;
168       j[54+3] =  0.0; j[54+4] =  0.5; j[54+5] =  0.0;
169       j[54+6] =  0.0; j[54+7] =  0.0; j[54+8] =  0.5;
170       /* H */
171       v[21+0] = -1.0; v[21+1] =  0.0; v[21+2] =  0.0;
172       j[63+0] =  0.5; j[63+1] =  0.0; j[63+2] =  0.0;
173       j[63+3] =  0.0; j[63+4] =  0.5; j[63+5] =  0.0;
174       j[63+6] =  0.0; j[63+7] =  0.0; j[63+8] =  0.5;
175       for (s = 0; s < 8; ++s) {
176         DMPlex_Det3D_Internal(&detJ, &j[s*dim*dim]);
177         DMPlex_Invert3D_Internal(&invj[s*dim*dim], &j[s*dim*dim], detJ);
178       }
179     }
180   default:
181     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
182   }
183   if (v0) {*v0 = v; *jac = j; *invjac = invj;}
184   PetscFunctionReturn(0);
185 }
186 
187 PetscErrorCode CellRefinerRestoreAffineTransforms_Internal(CellRefiner refiner, PetscInt *numSubcells, PetscReal *v0[], PetscReal *jac[], PetscReal *invjac[])
188 {
189   PetscErrorCode ierr;
190 
191   PetscFunctionBegin;
192   ierr = PetscFree3(*v0,*jac,*invjac);CHKERRQ(ierr);
193   PetscFunctionReturn(0);
194 }
195 
196 /* Should this be here or in the DualSpace somehow? */
197 PetscErrorCode CellRefinerInCellTest_Internal(CellRefiner refiner, const PetscReal point[], PetscBool *inside)
198 {
199   PetscReal sum = 0.0;
200   PetscInt  d;
201 
202   PetscFunctionBegin;
203   *inside = PETSC_TRUE;
204   switch (refiner) {
205   case REFINER_NOOP: break;
206   case REFINER_SIMPLEX_2D:
207     for (d = 0; d < 2; ++d) {
208       if (point[d] < -1.0) {*inside = PETSC_FALSE; break;}
209       sum += point[d];
210     }
211     if (sum > 1.0e-10) {*inside = PETSC_FALSE; break;}
212     break;
213   case REFINER_HEX_2D:
214     for (d = 0; d < 2; ++d) if ((point[d] < -1.00000000001) || (point[d] > 1.000000000001)) {*inside = PETSC_FALSE; break;}
215     break;
216   default:
217     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
218   }
219   PetscFunctionReturn(0);
220 }
221 
222 static PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[])
223 {
224   PetscInt       cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax;
225   PetscErrorCode ierr;
226 
227   PetscFunctionBegin;
228   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
229   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
230   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
231   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
232   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
233   switch (refiner) {
234   case REFINER_NOOP:
235     break;
236   case REFINER_SIMPLEX_1D:
237     depthSize[0] = vEnd - vStart + cEnd - cStart;         /* Add a vertex on every cell. */
238     depthSize[1] = 2*(cEnd - cStart);                     /* Split every cell in 2. */
239     break;
240   case REFINER_SIMPLEX_2D:
241     depthSize[0] = vEnd - vStart + fEnd - fStart;         /* Add a vertex on every face */
242     depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */
243     depthSize[2] = 4*(cEnd - cStart);                     /* Every cell split into 4 cells */
244     break;
245   case REFINER_HYBRID_SIMPLEX_2D:
246     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
247     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
248     depthSize[0] = vEnd - vStart + fMax - fStart;                                         /* Add a vertex on every face, but not hybrid faces */
249     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 */
250     depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax);                                   /* Interior cells split into 4 cells, hybrid cells split into 2 cells */
251     break;
252   case REFINER_SIMPLEX_TO_HEX_2D:
253     depthSize[0] = vEnd - vStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every face and cell */
254     depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart);         /* Every face is split into 2 faces and 3 faces are added for each cell */
255     depthSize[2] = 3*(cEnd - cStart);                             /* Every cell split into 3 cells */
256     break;
257   case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
258     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
259     depthSize[0] = vEnd - vStart + fEnd - fStart + cEnd - cStart;           /* Add a vertex on every face and cell */
260     depthSize[1] = 2*(fEnd - fStart) + 3*(cMax - cStart) + 4*(cEnd - cMax); /* Every face is split into 2 faces and 3 faces are added for each cell. 4 for each hybrid cell */
261     depthSize[2] = 3*(cMax - cStart) + 4*(cEnd - cMax);                     /* Every cell split into 3 cells, hybrid cells split in 4 */
262     break;
263   case REFINER_HEX_2D:
264     depthSize[0] = vEnd - vStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every face and cell */
265     depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart);         /* Every face is split into 2 faces and 4 faces are added for each cell */
266     depthSize[2] = 4*(cEnd - cStart);                             /* Every cell split into 4 cells */
267     break;
268   case REFINER_HYBRID_HEX_2D:
269     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
270     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
271     /* Quadrilateral */
272     depthSize[0] = vEnd - vStart + fMax - fStart + cMax - cStart;                 /* Add a vertex on every face and cell */
273     depthSize[1] = 2*(fMax - fStart) + 4*(cMax - cStart);                         /* Every face is split into 2 faces, and 4 faces are added for each cell */
274     depthSize[2] = 4*(cMax - cStart);                                             /* Every cell split into 4 cells */
275     /* Segment Prisms */
276     depthSize[0] += 0;                                                            /* No hybrid vertices */
277     depthSize[1] +=   (fEnd - fMax)  +   (cEnd - cMax);                           /* Every hybrid face remains and 1 faces is added for each hybrid cell */
278     depthSize[2] += 2*(cEnd - cMax);                                              /* Every hybrid cell split into 2 cells */
279     break;
280   case REFINER_SIMPLEX_3D:
281     depthSize[0] =    vEnd - vStart  +    eEnd - eStart;                    /* Add a vertex on every edge */
282     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 */
283     depthSize[2] = 4*(fEnd - fStart) + 8*(cEnd - cStart);                   /* Every face split into 4 faces and 8 faces are added for each cell */
284     depthSize[3] = 8*(cEnd - cStart);                                       /* Every cell split into 8 cells */
285     break;
286   case REFINER_HYBRID_SIMPLEX_3D:
287     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
288     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
289     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
290     /* Tetrahedra */
291     depthSize[0]  =    vEnd - vStart  +    eMax - eStart;                    /* Add a vertex on every interior edge */
292     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 */
293     depthSize[2]  = 4*(fMax - fStart) + 8*(cMax - cStart);                   /* Every interior face split into 4 faces, 8 faces added for each interior cell */
294     depthSize[3]  = 8*(cMax - cStart);                                       /* Every interior cell split into 8 cells */
295     /* Triangular Prisms */
296     depthSize[0] += 0;                                                       /* No hybrid vertices */
297     depthSize[1] +=   (eEnd - eMax)   +   (fEnd - fMax);                     /* Every hybrid edge remains, 1 edge for every hybrid face */
298     depthSize[2] += 2*(fEnd - fMax)   + 3*(cEnd - cMax);                     /* Every hybrid face split into 2 faces and 3 faces are added for each hybrid cell */
299     depthSize[3] += 4*(cEnd - cMax);                                         /* Every hybrid cell split into 4 cells */
300     break;
301   case REFINER_SIMPLEX_TO_HEX_3D:
302     depthSize[0] = vEnd - vStart + fEnd - fStart + eEnd - eStart + cEnd - cStart; /* Add a vertex on every face, edge and cell */
303     depthSize[1] = 2*(eEnd - eStart) + 3*(fEnd - fStart) + 4*(cEnd - cStart);     /* Every edge is split into 2 edges, 3 edges are added for each face, and 4 for each cell */
304     depthSize[2] = 3*(fEnd - fStart) + 6*(cEnd - cStart);                         /* Every face is split into 3 faces and 6 faces are added for each cell */
305     depthSize[3] = 4*(cEnd - cStart);                                             /* Every cell split into 4 cells */
306     break;
307   case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
308     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
309     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
310     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
311     /* Tetrahedra */
312     depthSize[0]  =    vEnd - vStart  +    eMax - eStart  + fMax - fStart + cMax - cStart; /* Add a vertex on every interior edge, face and cell */
313     depthSize[1]  = 2*(eMax - eStart) + 3*(fMax - fStart) + 4*(cMax - cStart);             /* Every interior edge split into 2 edges, 3 edges added for each interior face, 4 edges for each interior cell */
314     depthSize[2]  = 3*(fMax - fStart) + 6*(cMax - cStart);                                 /* Every interior face split into 3 faces, 6 faces added for each interior cell */
315     depthSize[3]  = 4*(cMax - cStart);                                                     /* Every interior cell split into 8 cells */
316     /* Triangular Prisms */
317     depthSize[0] += 0;                                                 /* No hybrid vertices */
318     depthSize[1] +=   (eEnd - eMax) +   (fEnd - fMax) + (cEnd - cMax); /* Every hybrid edge remains, 1 edge for every hybrid face and cell */
319     depthSize[2] += 2*(fEnd - fMax) + 3*(cEnd - cMax);                 /* Every hybrid face split into 2 faces and 3 faces are added for each hybrid cell */
320     depthSize[3] += 3*(cEnd - cMax);                                   /* Every hybrid cell split into 3 cells */
321     break;
322   case REFINER_HEX_3D:
323     depthSize[0] = vEnd - vStart + eEnd - eStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every edge, face and cell */
324     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 */
325     depthSize[2] = 4*(fEnd - fStart) + 12*(cEnd - cStart);                        /* Every face is split into 4 faces, and 12 faces are added for each cell */
326     depthSize[3] = 8*(cEnd - cStart);                                             /* Every cell split into 8 cells */
327     break;
328   case REFINER_HYBRID_HEX_3D:
329     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
330     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
331     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
332     /* Hexahedra */
333     depthSize[0] = vEnd - vStart + eMax - eStart + fMax - fStart + cMax - cStart; /* Add a vertex on every edge, face and cell */
334     depthSize[1] = 2*(eMax - eStart) +  4*(fMax - fStart) + 6*(cMax - cStart);    /* Every edge is split into 2 edge, 4 edges are added for each face, and 6 edges for each cell */
335     depthSize[2] = 4*(fMax - fStart) + 12*(cMax - cStart);                        /* Every face is split into 4 faces, and 12 faces are added for each cell */
336     depthSize[3] = 8*(cMax - cStart);                                             /* Every cell split into 8 cells */
337     /* Quadrilateral Prisms */
338     depthSize[0] += 0;                                                            /* No hybrid vertices */
339     depthSize[1] +=   (eEnd - eMax)   +   (fEnd - fMax)   +   (cEnd - cMax);      /* Every hybrid edge remains, 1 edge for every hybrid face and hybrid cell */
340     depthSize[2] += 2*(fEnd - fMax)   + 4*(cEnd - cMax);                          /* Every hybrid face split into 2 faces and 4 faces are added for each hybrid cell */
341     depthSize[3] += 4*(cEnd - cMax);                                              /* Every hybrid cell split into 4 cells */
342     break;
343   default:
344     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
345   }
346   PetscFunctionReturn(0);
347 }
348 
349 /* Return triangle edge for orientation o, if it is r for o == 0 */
350 PETSC_STATIC_INLINE PetscInt GetTriEdge_Static(PetscInt o, PetscInt r) {
351   return (o < 0 ? 2-(o+r) : o+r)%3;
352 }
353 PETSC_STATIC_INLINE PetscInt GetTriEdgeInverse_Static(PetscInt o, PetscInt s) {
354   return (o < 0 ? 2-(o+s) : 3+s-o)%3;
355 }
356 
357 /* Return triangle subface for orientation o, if it is r for o == 0 */
358 PETSC_STATIC_INLINE PetscInt GetTriSubface_Static(PetscInt o, PetscInt r) {
359   return (o < 0 ? 3-(o+r) : o+r)%3;
360 }
361 PETSC_STATIC_INLINE PetscInt GetTriSubfaceInverse_Static(PetscInt o, PetscInt s) {
362   return (o < 0 ? 3-(o+s) : 3+s-o)%3;
363 }
364 
365 /* Return the interior edge number connecting the midpoints of the triangle edges r
366    and r+1 in the transitive closure for triangle orientation o */
367 PETSC_STATIC_INLINE PetscInt GetTriMidEdge_Static(PetscInt o, PetscInt r) {
368   return (o < 0 ? 1-(o+r) : o+r)%3;
369 }
370 PETSC_STATIC_INLINE PetscInt GetTriMidEdgeInverse_Static(PetscInt o, PetscInt s) {
371   return (o < 0 ? 1-(o+s) : 3+s-o)%3;
372 }
373 
374 /* Return the interior edge number connecting the midpoint of the triangle edge r
375    (in the transitive closure) and the vertex in the interior of the face for triangle orientation o */
376 PETSC_STATIC_INLINE PetscInt GetTriInteriorEdge_Static(PetscInt o, PetscInt r) {
377   return (o < 0 ? 2-(o+r) : o+r)%3;
378 }
379 PETSC_STATIC_INLINE PetscInt GetTriInteriorEdgeInverse_Static(PetscInt o, PetscInt s) {
380   return (o < 0 ? 2-(o+s) : 3+s-o)%3;
381 }
382 
383 /* Return quad edge for orientation o, if it is r for o == 0 */
384 PETSC_STATIC_INLINE PetscInt GetQuadEdge_Static(PetscInt o, PetscInt r) {
385   return (o < 0 ? 3-(o+r) : o+r)%4;
386 }
387 PETSC_STATIC_INLINE PetscInt GetQuadEdgeInverse_Static(PetscInt o, PetscInt s) {
388   return (o < 0 ? 3-(o+s) : 4+s-o)%4;
389 }
390 
391 /* Return quad subface for orientation o, if it is r for o == 0 */
392 PETSC_STATIC_INLINE PetscInt GetQuadSubface_Static(PetscInt o, PetscInt r) {
393   return (o < 0 ? 4-(o+r) : o+r)%4;
394 }
395 PETSC_STATIC_INLINE PetscInt GetQuadSubfaceInverse_Static(PetscInt o, PetscInt s) {
396   return (o < 0 ? 4-(o+s) : 4+s-o)%4;
397 }
398 
399 static PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt cStart, PetscInt cEnd)
400 {
401   IS             cIS;
402   PetscErrorCode ierr;
403 
404   PetscFunctionBegin;
405   ierr = ISCreateStride(PETSC_COMM_SELF, cEnd - cStart, cStart, 1, &cIS);CHKERRQ(ierr);
406   ierr = DMLabelSetStratumIS(label, value, cIS);CHKERRQ(ierr);
407   ierr = ISDestroy(&cIS);CHKERRQ(ierr);
408   PetscFunctionReturn(0);
409 }
410 
411 static PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
412 {
413   PetscInt       depth, cStart, cStartNew, cEnd, cEndNew, cMax, c, vStart, vStartNew, vEnd, vEndNew, vMax, v, fStart, fStartNew, fEnd, fEndNew, fMax, f, eStart, eStartNew, eEnd, eEndNew, eMax, e, r;
414   DMLabel        depthLabel;
415   PetscErrorCode ierr;
416 
417   PetscFunctionBegin;
418   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
419   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
420   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
421   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
422   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
423   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
424   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
425   ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr);
426   ierr = DMCreateLabel(rdm,"depth");CHKERRQ(ierr);
427   ierr = DMPlexGetDepthLabel(rdm,&depthLabel);CHKERRQ(ierr);
428   ierr = DMLabelSetStratumBounds(depthLabel, 0, vStartNew, vEndNew);CHKERRQ(ierr);
429   if (depth > 2) ierr = DMLabelSetStratumBounds(depthLabel, 1, eStartNew, eEndNew);CHKERRQ(ierr);
430   if (depth > 1) ierr = DMLabelSetStratumBounds(depthLabel, depth - 1, fStartNew, fEndNew);CHKERRQ(ierr);
431   if (depth > 0) ierr = DMLabelSetStratumBounds(depthLabel, depth, cStartNew, cEndNew);CHKERRQ(ierr);
432   {
433     DM_Plex *plex = (DM_Plex *) rdm->data;
434     ierr = PetscObjectStateGet((PetscObject) depthLabel, &plex->depthState);CHKERRQ(ierr);
435   }
436   if (!refiner) PetscFunctionReturn(0);
437   switch (refiner) {
438   case REFINER_SIMPLEX_1D:
439     /* All cells have 2 vertices */
440     for (c = cStart; c < cEnd; ++c) {
441       for (r = 0; r < 2; ++r) {
442         const PetscInt newp = cStartNew + (c - cStart)*2 + r;
443 
444         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
445       }
446     }
447     /* Old vertices have identical supports */
448     for (v = vStart; v < vEnd; ++v) {
449       const PetscInt newp = vStartNew + (v - vStart);
450       PetscInt       size;
451 
452       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
453       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
454     }
455     /* Cell vertices have support 2 */
456     for (c = cStart; c < cEnd; ++c) {
457       const PetscInt newp = vStartNew + (vEnd - vStart) + (c - cStart);
458 
459       ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
460     }
461     break;
462   case REFINER_SIMPLEX_2D:
463     /* All cells have 3 faces */
464     for (c = cStart; c < cEnd; ++c) {
465       for (r = 0; r < 4; ++r) {
466         const PetscInt newp = (c - cStart)*4 + r;
467 
468         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
469       }
470     }
471     /* Split faces have 2 vertices and the same cells as the parent */
472     for (f = fStart; f < fEnd; ++f) {
473       for (r = 0; r < 2; ++r) {
474         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
475         PetscInt       size;
476 
477         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
478         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
479         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
480       }
481     }
482     /* Interior faces have 2 vertices and 2 cells */
483     for (c = cStart; c < cEnd; ++c) {
484       for (r = 0; r < 3; ++r) {
485         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
486 
487         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
488         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
489       }
490     }
491     /* Old vertices have identical supports */
492     for (v = vStart; v < vEnd; ++v) {
493       const PetscInt newp = vStartNew + (v - vStart);
494       PetscInt       size;
495 
496       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
497       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
498     }
499     /* Face vertices have 2 + cells*2 supports */
500     for (f = fStart; f < fEnd; ++f) {
501       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
502       PetscInt       size;
503 
504       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
505       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr);
506     }
507     break;
508   case REFINER_SIMPLEX_TO_HEX_2D:
509     /* All cells have 4 faces */
510     for (c = cStart; c < cEnd; ++c) {
511       for (r = 0; r < 3; ++r) {
512         const PetscInt newp = (c - cStart)*3 + r;
513 
514         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
515       }
516     }
517     /* Split faces have 2 vertices and the same cells as the parent */
518     for (f = fStart; f < fEnd; ++f) {
519       for (r = 0; r < 2; ++r) {
520         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
521         PetscInt       size;
522 
523         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
524         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
525         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
526       }
527     }
528     /* Interior faces have 2 vertices and 2 cells */
529     for (c = cStart; c < cEnd; ++c) {
530       for (r = 0; r < 3; ++r) {
531         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
532 
533         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
534         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
535       }
536     }
537     /* Old vertices have identical supports */
538     for (v = vStart; v < vEnd; ++v) {
539       const PetscInt newp = vStartNew + (v - vStart);
540       PetscInt       size;
541 
542       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
543       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
544     }
545     /* Split-face vertices have cells + 2 supports */
546     for (f = fStart; f < fEnd; ++f) {
547       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
548       PetscInt       size;
549 
550       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
551       ierr = DMPlexSetSupportSize(rdm, newp, size + 2);CHKERRQ(ierr);
552     }
553     /* Interior vertices have 3 supports */
554     for (c = cStart; c < cEnd; ++c) {
555       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;
556 
557       ierr = DMPlexSetSupportSize(rdm, newp, 3);CHKERRQ(ierr);
558     }
559     break;
560   case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
561     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
562     /* the mesh is no longer hybrid */
563     cMax = PetscMin(cEnd, cMax);
564     /* All cells have 4 faces */
565     for (c = cStart; c < cMax; ++c) {
566       for (r = 0; r < 3; ++r) {
567         const PetscInt newp = (c - cStart)*3 + r;
568 
569         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
570       }
571     }
572     for (c = cMax; c < cEnd; ++c) {
573       for (r = 0; r < 4; ++r) {
574         const PetscInt newp = (cMax - cStart)*3 + (c - cMax)*4 + r;
575 
576         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
577       }
578     }
579     /* Split faces have 2 vertices and the same cells as the parent */
580     for (f = fStart; f < fEnd; ++f) {
581       for (r = 0; r < 2; ++r) {
582         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
583         PetscInt       size;
584 
585         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
586         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
587         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
588       }
589     }
590     /* Interior faces have 2 vertices and 2 cells */
591     for (c = cStart; c < cMax; ++c) {
592       for (r = 0; r < 3; ++r) {
593         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
594 
595         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
596         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
597       }
598     }
599     /* Hybrid interior faces have 2 vertices and 2 cells */
600     for (c = cMax; c < cEnd; ++c) {
601       for (r = 0; r < 4; ++r) {
602         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (c - cMax)*4 + r;
603 
604         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
605         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
606       }
607     }
608     /* Old vertices have identical supports */
609     for (v = vStart; v < vEnd; ++v) {
610       const PetscInt newp = vStartNew + (v - vStart);
611       PetscInt       size;
612 
613       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
614       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
615     }
616     /* Split-face vertices have cells + 2 supports */
617     for (f = fStart; f < fEnd; ++f) {
618       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
619       PetscInt       size;
620 
621       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
622       ierr = DMPlexSetSupportSize(rdm, newp, size + 2);CHKERRQ(ierr);
623     }
624     /* Interior vertices have 3 supports */
625     for (c = cStart; c < cMax; ++c) {
626       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;
627 
628       ierr = DMPlexSetSupportSize(rdm, newp, 3);CHKERRQ(ierr);
629     }
630     /* Hybrid interior vertices have 4 supports */
631     for (c = cMax; c < cEnd; ++c) {
632       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;
633 
634       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
635     }
636     break;
637   case REFINER_HEX_2D:
638     /* All cells have 4 faces */
639     for (c = cStart; c < cEnd; ++c) {
640       for (r = 0; r < 4; ++r) {
641         const PetscInt newp = cStartNew + (c - cStart)*4 + r;
642 
643         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
644       }
645     }
646     /* Split faces have 2 vertices and the same cells as the parent */
647     for (f = fStart; f < fEnd; ++f) {
648       for (r = 0; r < 2; ++r) {
649         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
650         PetscInt       size;
651 
652         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
653         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
654         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
655       }
656     }
657     /* Interior faces have 2 vertices and 2 cells */
658     for (c = cStart; c < cEnd; ++c) {
659       for (r = 0; r < 4; ++r) {
660         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
661 
662         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
663         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
664       }
665     }
666     /* Old vertices have identical supports */
667     for (v = vStart; v < vEnd; ++v) {
668       const PetscInt newp = vStartNew + (v - vStart);
669       PetscInt       size;
670 
671       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
672       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
673     }
674     /* Face vertices have 2 + cells supports */
675     for (f = fStart; f < fEnd; ++f) {
676       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
677       PetscInt       size;
678 
679       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
680       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
681     }
682     /* Cell vertices have 4 supports */
683     for (c = cStart; c < cEnd; ++c) {
684       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
685 
686       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
687     }
688     break;
689   case REFINER_HYBRID_SIMPLEX_2D:
690     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
691     cMax = PetscMin(cEnd, cMax);
692     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
693     fMax = PetscMin(fEnd, fMax);
694     ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
695     /* Interior cells have 3 faces */
696     for (c = cStart; c < cMax; ++c) {
697       for (r = 0; r < 4; ++r) {
698         const PetscInt newp = cStartNew + (c - cStart)*4 + r;
699 
700         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
701       }
702     }
703     /* Hybrid cells have 4 faces */
704     for (c = cMax; c < cEnd; ++c) {
705       for (r = 0; r < 2; ++r) {
706         const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
707 
708         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
709       }
710     }
711     /* Interior split faces have 2 vertices and the same cells as the parent */
712     for (f = fStart; f < fMax; ++f) {
713       for (r = 0; r < 2; ++r) {
714         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
715         PetscInt       size;
716 
717         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
718         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
719         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
720       }
721     }
722     /* Interior cell faces have 2 vertices and 2 cells */
723     for (c = cStart; c < cMax; ++c) {
724       for (r = 0; r < 3; ++r) {
725         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
726 
727         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
728         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
729       }
730     }
731     /* Hybrid faces have 2 vertices and the same cells */
732     for (f = fMax; f < fEnd; ++f) {
733       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
734       PetscInt       size;
735 
736       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
737       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
738       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
739     }
740     /* Hybrid cell faces have 2 vertices and 2 cells */
741     for (c = cMax; c < cEnd; ++c) {
742       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
743 
744       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
745       ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
746     }
747     /* Old vertices have identical supports */
748     for (v = vStart; v < vEnd; ++v) {
749       const PetscInt newp = vStartNew + (v - vStart);
750       PetscInt       size;
751 
752       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
753       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
754     }
755     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
756     for (f = fStart; f < fMax; ++f) {
757       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
758       const PetscInt *support;
759       PetscInt       size, newSize = 2, s;
760 
761       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
762       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
763       for (s = 0; s < size; ++s) {
764         if (support[s] >= cMax) newSize += 1;
765         else newSize += 2;
766       }
767       ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr);
768     }
769     break;
770   case REFINER_HYBRID_HEX_2D:
771     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
772     cMax = PetscMin(cEnd, cMax);
773     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
774     fMax = PetscMin(fEnd, fMax);
775     ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
776     /* Interior cells have 4 faces */
777     for (c = cStart; c < cMax; ++c) {
778       for (r = 0; r < 4; ++r) {
779         const PetscInt newp = cStartNew + (c - cStart)*4 + r;
780 
781         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
782       }
783     }
784     /* Hybrid cells have 4 faces */
785     for (c = cMax; c < cEnd; ++c) {
786       for (r = 0; r < 2; ++r) {
787         const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
788 
789         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
790       }
791     }
792     /* Interior split faces have 2 vertices and the same cells as the parent */
793     for (f = fStart; f < fMax; ++f) {
794       for (r = 0; r < 2; ++r) {
795         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
796         PetscInt       size;
797 
798         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
799         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
800         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
801       }
802     }
803     /* Interior cell faces have 2 vertices and 2 cells */
804     for (c = cStart; c < cMax; ++c) {
805       for (r = 0; r < 4; ++r) {
806         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
807 
808         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
809         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
810       }
811     }
812     /* Hybrid faces have 2 vertices and the same cells */
813     for (f = fMax; f < fEnd; ++f) {
814       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (f - fMax);
815       PetscInt       size;
816 
817       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
818       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
819       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
820     }
821     /* Hybrid cell faces have 2 vertices and 2 cells */
822     for (c = cMax; c < cEnd; ++c) {
823       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
824 
825       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
826       ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
827     }
828     /* Old vertices have identical supports */
829     for (v = vStart; v < vEnd; ++v) {
830       const PetscInt newp = vStartNew + (v - vStart);
831       PetscInt       size;
832 
833       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
834       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
835     }
836     /* Face vertices have 2 + cells supports */
837     for (f = fStart; f < fMax; ++f) {
838       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
839       PetscInt       size;
840 
841       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
842       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
843     }
844     /* Cell vertices have 4 supports */
845     for (c = cStart; c < cMax; ++c) {
846       const PetscInt newp = vStartNew + (vEnd - vStart) + (fMax - fStart) + (c - cStart);
847 
848       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
849     }
850     break;
851   case REFINER_SIMPLEX_3D:
852     /* All cells have 4 faces */
853     for (c = cStart; c < cEnd; ++c) {
854       for (r = 0; r < 8; ++r) {
855         const PetscInt newp = cStartNew + (c - cStart)*8 + r;
856 
857         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
858       }
859     }
860     /* Split faces have 3 edges and the same cells as the parent */
861     for (f = fStart; f < fEnd; ++f) {
862       for (r = 0; r < 4; ++r) {
863         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
864         PetscInt       size;
865 
866         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
867         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
868         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
869       }
870     }
871     /* Interior cell faces have 3 edges and 2 cells */
872     for (c = cStart; c < cEnd; ++c) {
873       for (r = 0; r < 8; ++r) {
874         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + r;
875 
876         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
877         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
878       }
879     }
880     /* Split edges have 2 vertices and the same faces */
881     for (e = eStart; e < eEnd; ++e) {
882       for (r = 0; r < 2; ++r) {
883         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
884         PetscInt       size;
885 
886         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
887         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
888         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
889       }
890     }
891     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
892     for (f = fStart; f < fEnd; ++f) {
893       for (r = 0; r < 3; ++r) {
894         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
895         const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
896         PetscInt        coneSize, c, supportSize, s, er, intFaces = 0;
897 
898         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
899         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
900         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
901         for (s = 0; s < supportSize; ++s) {
902           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
903           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
904           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
905           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
906           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
907           er = GetTriMidEdgeInverse_Static(ornt[c], r);
908           if (er == eint[c]) {
909             intFaces += 1;
910           } else {
911             intFaces += 2;
912           }
913         }
914         ierr = DMPlexSetSupportSize(rdm, newp, 2+intFaces);CHKERRQ(ierr);
915       }
916     }
917     /* Interior cell edges have 2 vertices and 4 faces */
918     for (c = cStart; c < cEnd; ++c) {
919       const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
920 
921       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
922       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
923     }
924     /* Old vertices have identical supports */
925     for (v = vStart; v < vEnd; ++v) {
926       const PetscInt newp = vStartNew + (v - vStart);
927       PetscInt       size;
928 
929       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
930       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
931     }
932     /* Edge vertices have 2 + faces*2 + cells*0/1 supports */
933     for (e = eStart; e < eEnd; ++e) {
934       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
935       PetscInt       size, *star = NULL, starSize, s, cellSize = 0;
936 
937       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
938       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
939       for (s = 0; s < starSize*2; s += 2) {
940         const PetscInt *cone, *ornt;
941         PetscInt        e01, e23;
942 
943         if ((star[s] >= cStart) && (star[s] < cEnd)) {
944           /* Check edge 0-1 */
945           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
946           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
947           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
948           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
949           /* Check edge 2-3 */
950           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
951           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
952           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
953           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
954           if ((e01 == e) || (e23 == e)) ++cellSize;
955         }
956       }
957       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
958       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2 + cellSize);CHKERRQ(ierr);
959     }
960     break;
961   case REFINER_HYBRID_SIMPLEX_3D:
962     ierr = DMPlexSetHybridBounds(rdm, cStartNew + 8*(cMax-cStart), fStartNew + 4*(fMax - fStart) + 8*(cMax - cStart),
963                                  eStartNew + 2*(eMax - eStart) + 3*(fMax - fStart) + (cMax - cStart), PETSC_DETERMINE);CHKERRQ(ierr);
964     /* Interior cells have 4 faces */
965     for (c = cStart; c < cMax; ++c) {
966       for (r = 0; r < 8; ++r) {
967         const PetscInt newp = cStartNew + (c - cStart)*8 + r;
968 
969         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
970       }
971     }
972     /* Hybrid cells have 5 faces */
973     for (c = cMax; c < cEnd; ++c) {
974       for (r = 0; r < 4; ++r) {
975         const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;
976 
977         ierr = DMPlexSetConeSize(rdm, newp, 5);CHKERRQ(ierr);
978       }
979     }
980     /* Interior split faces have 3 edges and the same cells as the parent */
981     for (f = fStart; f < fMax; ++f) {
982       for (r = 0; r < 4; ++r) {
983         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
984         PetscInt       size;
985 
986         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
987         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
988         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
989       }
990     }
991     /* Interior cell faces have 3 edges and 2 cells */
992     for (c = cStart; c < cMax; ++c) {
993       for (r = 0; r < 8; ++r) {
994         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + r;
995 
996         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
997         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
998       }
999     }
1000     /* Hybrid split faces have 4 edges and the same cells as the parent */
1001     for (f = fMax; f < fEnd; ++f) {
1002       for (r = 0; r < 2; ++r) {
1003         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;
1004         PetscInt       size;
1005 
1006         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1007         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1008         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1009       }
1010     }
1011     /* Hybrid cells faces have 4 edges and 2 cells */
1012     for (c = cMax; c < cEnd; ++c) {
1013       for (r = 0; r < 3; ++r) {
1014         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + r;
1015 
1016         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1017         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
1018       }
1019     }
1020     /* Interior split edges have 2 vertices and the same faces */
1021     for (e = eStart; e < eMax; ++e) {
1022       for (r = 0; r < 2; ++r) {
1023         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1024         PetscInt       size;
1025 
1026         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1027         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1028         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1029       }
1030     }
1031     /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
1032     for (f = fStart; f < fMax; ++f) {
1033       for (r = 0; r < 3; ++r) {
1034         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
1035         const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
1036         PetscInt        coneSize, c, supportSize, s, er, intFaces = 0;
1037 
1038         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1039         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1040         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1041         for (s = 0; s < supportSize; ++s) {
1042           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1043           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1044           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1045           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
1046           if (support[s] < cMax) {
1047             /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
1048             er = GetTriMidEdgeInverse_Static(ornt[c], r);
1049             if (er == eint[c]) {
1050               intFaces += 1;
1051             } else {
1052               intFaces += 2;
1053             }
1054           } else {
1055             intFaces += 1;
1056           }
1057         }
1058         ierr = DMPlexSetSupportSize(rdm, newp, 2+intFaces);CHKERRQ(ierr);
1059       }
1060     }
1061     /* Interior cell edges have 2 vertices and 4 faces */
1062     for (c = cStart; c < cMax; ++c) {
1063       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
1064 
1065       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1066       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
1067     }
1068     /* Hybrid edges have 2 vertices and the same faces */
1069     for (e = eMax; e < eEnd; ++e) {
1070       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
1071       PetscInt       size;
1072 
1073       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1074       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1075       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1076     }
1077     /* Hybrid face edges have 2 vertices and 2+2*cells faces */
1078     for (f = fMax; f < fEnd; ++f) {
1079       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
1080       PetscInt       size;
1081 
1082       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1083       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1084       ierr = DMPlexSetSupportSize(rdm, newp, 2+2*size);CHKERRQ(ierr);
1085     }
1086     /* Interior vertices have identical supports */
1087     for (v = vStart; v < vEnd; ++v) {
1088       const PetscInt newp = vStartNew + (v - vStart);
1089       PetscInt       size;
1090 
1091       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
1092       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1093     }
1094     /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
1095     for (e = eStart; e < eMax; ++e) {
1096       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
1097       const PetscInt *support;
1098       PetscInt        size, *star = NULL, starSize, s, faceSize = 0, cellSize = 0;
1099 
1100       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1101       ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
1102       for (s = 0; s < size; ++s) {
1103         if (support[s] < fMax) faceSize += 2;
1104         else                   faceSize += 1;
1105       }
1106       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
1107       for (s = 0; s < starSize*2; s += 2) {
1108         const PetscInt *cone, *ornt;
1109         PetscInt        e01, e23;
1110 
1111         if ((star[s] >= cStart) && (star[s] < cMax)) {
1112           /* Check edge 0-1 */
1113           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
1114           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
1115           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
1116           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
1117           /* Check edge 2-3 */
1118           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
1119           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
1120           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
1121           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
1122           if ((e01 == e) || (e23 == e)) ++cellSize;
1123         }
1124       }
1125       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
1126       ierr = DMPlexSetSupportSize(rdm, newp, 2 + faceSize + cellSize);CHKERRQ(ierr);
1127     }
1128     break;
1129   case REFINER_SIMPLEX_TO_HEX_3D:
1130     /* All cells have 6 faces */
1131     for (c = cStart; c < cEnd; ++c) {
1132       for (r = 0; r < 4; ++r) {
1133         const PetscInt newp = cStartNew + (c - cStart)*4 + r;
1134 
1135         ierr = DMPlexSetConeSize(rdm, newp, 6);CHKERRQ(ierr);
1136       }
1137     }
1138     /* Split faces have 4 edges and the same cells as the parent */
1139     for (f = fStart; f < fEnd; ++f) {
1140       for (r = 0; r < 3; ++r) {
1141         const PetscInt newp = fStartNew + (f - fStart)*3 + r;
1142         PetscInt       size;
1143 
1144         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1145         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1146         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1147       }
1148     }
1149     /* Interior cell faces have 4 edges and 2 cells */
1150     for (c = cStart; c < cEnd; ++c) {
1151       for (r = 0; r < 6; ++r) {
1152         const PetscInt newp = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + r;
1153 
1154         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1155         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
1156       }
1157     }
1158     /* Split edges have 2 vertices and the same faces */
1159     for (e = eStart; e < eEnd; ++e) {
1160       for (r = 0; r < 2; ++r) {
1161         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1162         PetscInt       size;
1163 
1164         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1165         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1166         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1167       }
1168     }
1169     /* Face edges have 2 vertices and 2 + cell faces supports */
1170     for (f = fStart; f < fEnd; ++f) {
1171       for (r = 0; r < 3; ++r) {
1172         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
1173         PetscInt        size;
1174 
1175         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1176         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1177         ierr = DMPlexSetSupportSize(rdm, newp, 2+size);CHKERRQ(ierr);
1178       }
1179     }
1180     /* Interior cell edges have 2 vertices and 3 faces */
1181     for (c = cStart; c < cEnd; ++c) {
1182       for (r = 0; r < 4; ++r) {
1183         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + r;
1184 
1185         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1186         ierr = DMPlexSetSupportSize(rdm, newp, 3);CHKERRQ(ierr);
1187       }
1188     }
1189     /* Old vertices have identical supports */
1190     for (v = vStart; v < vEnd; ++v) {
1191       const PetscInt newp = vStartNew + (v - vStart);
1192       PetscInt       size;
1193 
1194       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
1195       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1196     }
1197     /* Edge vertices have 2 + faces supports */
1198     for (e = eStart; e < eEnd; ++e) {
1199       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1200       PetscInt       size;
1201 
1202       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1203       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
1204     }
1205     /* Face vertices have 3 + cells supports */
1206     for (f = fStart; f < fEnd; ++f) {
1207       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + f - fStart;
1208       PetscInt       size;
1209 
1210       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1211       ierr = DMPlexSetSupportSize(rdm, newp, 3 + size);CHKERRQ(ierr);
1212     }
1213     /* Interior cell vertices have 4 supports */
1214     for (c = cStart; c < cEnd; ++c) {
1215       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + fEnd - fStart + c - cStart;
1216 
1217       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
1218     }
1219     break;
1220   case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
1221     /* the mesh is no longer hybrid */
1222     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
1223     cMax = PetscMin(cEnd, cMax);
1224     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
1225     fMax = PetscMin(fEnd, fMax);
1226     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
1227     eMax = PetscMin(eEnd, eMax);
1228     /* All cells have 6 faces */
1229     for (c = cStart; c < cMax; ++c) {
1230       for (r = 0; r < 4; ++r) {
1231         const PetscInt newp = cStartNew + (c - cStart)*4 + r;
1232 
1233         ierr = DMPlexSetConeSize(rdm, newp, 6);CHKERRQ(ierr);
1234       }
1235     }
1236     for (c = cMax; c < cEnd; ++c) {
1237       for (r = 0; r < 3; ++r) {
1238         const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + r;
1239 
1240         ierr = DMPlexSetConeSize(rdm, newp, 6);CHKERRQ(ierr);
1241       }
1242     }
1243     /* Interior split faces have 4 edges and the same cells as the parent */
1244     for (f = fStart; f < fMax; ++f) {
1245       for (r = 0; r < 3; ++r) {
1246         const PetscInt newp = fStartNew + (f - fStart)*3 + r;
1247         PetscInt       size;
1248 
1249         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1250         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1251         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1252       }
1253     }
1254     /* Interior cell faces have 4 edges and 2 cells */
1255     for (c = cStart; c < cMax; ++c) {
1256       for (r = 0; r < 6; ++r) {
1257         const PetscInt newp = fStartNew + (fMax - fStart)*3 + (c - cStart)*6 + r;
1258 
1259         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1260         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
1261       }
1262     }
1263     /* Hybrid split faces have 4 edges and the same cells as the parent */
1264     for (f = fMax; f < fEnd; ++f) {
1265       for (r = 0; r < 2; ++r) {
1266         const PetscInt newp = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (f - fMax)*2 + r;
1267         PetscInt       size;
1268 
1269         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1270         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1271         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1272       }
1273     }
1274     /* Hybrid cell faces have 4 edges and 2 cells */
1275     for (c = cMax; c < cEnd; ++c) {
1276       for (r = 0; r < 3; ++r) {
1277         const PetscInt newp = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + r;
1278 
1279         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1280         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
1281       }
1282     }
1283     /* Interior split edges have 2 vertices and the same faces */
1284     for (e = eStart; e < eMax; ++e) {
1285       for (r = 0; r < 2; ++r) {
1286         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1287         PetscInt       size;
1288 
1289         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1290         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1291         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1292       }
1293     }
1294     /* Interior face edges have 2 vertices and 2 + cell faces supports */
1295     for (f = fStart; f < fMax; ++f) {
1296       for (r = 0; r < 3; ++r) {
1297         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
1298         PetscInt        size;
1299 
1300         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1301         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1302         ierr = DMPlexSetSupportSize(rdm, newp, 2+size);CHKERRQ(ierr);
1303       }
1304     }
1305     /* Interior cell edges have 2 vertices and 3 faces */
1306     for (c = cStart; c < cMax; ++c) {
1307       for (r = 0; r < 4; ++r) {
1308         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + r;
1309 
1310         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1311         ierr = DMPlexSetSupportSize(rdm, newp, 3);CHKERRQ(ierr);
1312       }
1313     }
1314     /* Hybrid edges have 2 vertices and the same faces */
1315     for (e = eMax; e < eEnd; ++e) {
1316       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (e - eMax);
1317       PetscInt       size;
1318 
1319       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1320       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1321       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1322     }
1323     /* Hybrid face edges have 2 vertices and 2+cells faces */
1324     for (f = fMax; f < fEnd; ++f) {
1325       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (f - fMax);
1326       PetscInt        size;
1327 
1328       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1329       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1330       ierr = DMPlexSetSupportSize(rdm, newp, 2+size);CHKERRQ(ierr);
1331     }
1332     /* Hybrid cell edges have 2 vertices and 3 faces */
1333     for (c = cMax; c < cEnd; ++c) {
1334       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
1335 
1336       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1337       ierr = DMPlexSetSupportSize(rdm, newp, 3);CHKERRQ(ierr);
1338     }
1339     /* Old vertices have identical supports */
1340     for (v = vStart; v < vEnd; ++v) {
1341       const PetscInt newp = vStartNew + (v - vStart);
1342       PetscInt       size;
1343 
1344       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
1345       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1346     }
1347     /* Interior edge vertices have 2 + faces supports */
1348     for (e = eStart; e < eMax; ++e) {
1349       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1350       PetscInt       size;
1351 
1352       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1353       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
1354     }
1355     /* Interior face vertices have 3 + cells supports */
1356     for (f = fStart; f < fMax; ++f) {
1357       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + f - fStart;
1358       PetscInt       size;
1359 
1360       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1361       ierr = DMPlexSetSupportSize(rdm, newp, 3 + size);CHKERRQ(ierr);
1362     }
1363     /* Interior cell vertices have 4 supports */
1364     for (c = cStart; c < cMax; ++c) {
1365       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + c - cStart;
1366 
1367       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
1368     }
1369     break;
1370   case REFINER_HEX_3D:
1371     /* All cells have 6 faces */
1372     for (c = cStart; c < cEnd; ++c) {
1373       for (r = 0; r < 8; ++r) {
1374         const PetscInt newp = (c - cStart)*8 + r;
1375 
1376         ierr = DMPlexSetConeSize(rdm, newp, 6);CHKERRQ(ierr);
1377       }
1378     }
1379     /* Split faces have 4 edges and the same cells as the parent */
1380     for (f = fStart; f < fEnd; ++f) {
1381       for (r = 0; r < 4; ++r) {
1382         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
1383         PetscInt       size;
1384 
1385         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1386         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1387         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1388       }
1389     }
1390     /* Interior faces have 4 edges and 2 cells */
1391     for (c = cStart; c < cEnd; ++c) {
1392       for (r = 0; r < 12; ++r) {
1393         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
1394 
1395         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1396         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
1397       }
1398     }
1399     /* Split edges have 2 vertices and the same faces as the parent */
1400     for (e = eStart; e < eEnd; ++e) {
1401       for (r = 0; r < 2; ++r) {
1402         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1403         PetscInt       size;
1404 
1405         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1406         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1407         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1408       }
1409     }
1410     /* Face edges have 2 vertices and 2+cells faces */
1411     for (f = fStart; f < fEnd; ++f) {
1412       for (r = 0; r < 4; ++r) {
1413         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
1414         PetscInt       size;
1415 
1416         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1417         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1418         ierr = DMPlexSetSupportSize(rdm, newp, 2+size);CHKERRQ(ierr);
1419       }
1420     }
1421     /* Cell edges have 2 vertices and 4 faces */
1422     for (c = cStart; c < cEnd; ++c) {
1423       for (r = 0; r < 6; ++r) {
1424         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
1425 
1426         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1427         ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
1428       }
1429     }
1430     /* Old vertices have identical supports */
1431     for (v = vStart; v < vEnd; ++v) {
1432       const PetscInt newp = vStartNew + (v - vStart);
1433       PetscInt       size;
1434 
1435       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
1436       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1437     }
1438     /* Edge vertices have 2 + faces supports */
1439     for (e = eStart; e < eEnd; ++e) {
1440       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1441       PetscInt       size;
1442 
1443       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1444       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
1445     }
1446     /* Face vertices have 4 + cells supports */
1447     for (f = fStart; f < fEnd; ++f) {
1448       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
1449       PetscInt       size;
1450 
1451       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1452       ierr = DMPlexSetSupportSize(rdm, newp, 4 + size);CHKERRQ(ierr);
1453     }
1454     /* Cell vertices have 6 supports */
1455     for (c = cStart; c < cEnd; ++c) {
1456       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
1457 
1458       ierr = DMPlexSetSupportSize(rdm, newp, 6);CHKERRQ(ierr);
1459     }
1460     break;
1461   case REFINER_HYBRID_HEX_3D:
1462     ierr = DMPlexSetHybridBounds(rdm, cStartNew + 8*(cMax-cStart), fStartNew + 4*(fMax - fStart) + 12*(cMax - cStart),
1463                                  eStartNew + 2*(eMax - eStart) + 4*(fMax - fStart) + 6*(cMax - cStart), PETSC_DETERMINE);CHKERRQ(ierr);
1464     /* Interior cells have 6 faces */
1465     for (c = cStart; c < cMax; ++c) {
1466       for (r = 0; r < 8; ++r) {
1467         const PetscInt newp = cStartNew + (c - cStart)*8 + r;
1468 
1469         ierr = DMPlexSetConeSize(rdm, newp, 6);CHKERRQ(ierr);
1470       }
1471     }
1472     /* Hybrid cells have 6 faces */
1473     for (c = cMax; c < cEnd; ++c) {
1474       for (r = 0; r < 4; ++r) {
1475         const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;
1476 
1477         ierr = DMPlexSetConeSize(rdm, newp, 6);CHKERRQ(ierr);
1478       }
1479     }
1480     /* Interior split faces have 4 edges and the same cells as the parent */
1481     for (f = fStart; f < fMax; ++f) {
1482       for (r = 0; r < 4; ++r) {
1483         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
1484         PetscInt       size;
1485 
1486         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1487         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1488         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1489       }
1490     }
1491     /* Interior cell faces have 4 edges and 2 cells */
1492     for (c = cStart; c < cMax; ++c) {
1493       for (r = 0; r < 12; ++r) {
1494         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + r;
1495 
1496         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1497         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
1498       }
1499     }
1500     /* Hybrid split faces have 4 edges and the same cells as the parent */
1501     for (f = fMax; f < fEnd; ++f) {
1502       for (r = 0; r < 2; ++r) {
1503         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + r;
1504         PetscInt       size;
1505 
1506         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1507         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1508         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1509       }
1510     }
1511     /* Hybrid cells faces have 4 edges and 2 cells */
1512     for (c = cMax; c < cEnd; ++c) {
1513       for (r = 0; r < 4; ++r) {
1514         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + r;
1515 
1516         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
1517         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
1518       }
1519     }
1520     /* Interior split edges have 2 vertices and the same faces as the parent */
1521     for (e = eStart; e < eMax; ++e) {
1522       for (r = 0; r < 2; ++r) {
1523         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1524         PetscInt       size;
1525 
1526         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1527         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1528         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1529       }
1530     }
1531     /* Interior face edges have 2 vertices and 2+cells faces */
1532     for (f = fStart; f < fMax; ++f) {
1533       for (r = 0; r < 4; ++r) {
1534         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
1535         PetscInt       size;
1536 
1537         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1538         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1539         ierr = DMPlexSetSupportSize(rdm, newp, 2+size);CHKERRQ(ierr);
1540       }
1541     }
1542     /* Interior cell edges have 2 vertices and 4 faces */
1543     for (c = cStart; c < cMax; ++c) {
1544       for (r = 0; r < 6; ++r) {
1545         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
1546 
1547         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1548         ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
1549       }
1550     }
1551     /* Hybrid edges have 2 vertices and the same faces */
1552     for (e = eMax; e < eEnd; ++e) {
1553       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (e - eMax);
1554       PetscInt       size;
1555 
1556       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1557       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1558       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1559     }
1560     /* Hybrid face edges have 2 vertices and 2+cells faces */
1561     for (f = fMax; f < fEnd; ++f) {
1562       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
1563       PetscInt       size;
1564 
1565       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1566       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1567       ierr = DMPlexSetSupportSize(rdm, newp, 2+size);CHKERRQ(ierr);
1568     }
1569     /* Hybrid cell edges have 2 vertices and 4 faces */
1570     for (c = cMax; c < cEnd; ++c) {
1571       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
1572 
1573       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
1574       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
1575     }
1576     /* Interior vertices have identical supports */
1577     for (v = vStart; v < vEnd; ++v) {
1578       const PetscInt newp = vStartNew + (v - vStart);
1579       PetscInt       size;
1580 
1581       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
1582       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
1583     }
1584     /* Interior edge vertices have 2 + faces supports */
1585     for (e = eStart; e < eMax; ++e) {
1586       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1587       PetscInt       size;
1588 
1589       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1590       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
1591     }
1592     /* Interior face vertices have 4 + cells supports */
1593     for (f = fStart; f < fMax; ++f) {
1594       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
1595       PetscInt       size;
1596 
1597       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1598       ierr = DMPlexSetSupportSize(rdm, newp, 4 + size);CHKERRQ(ierr);
1599     }
1600     /* Interior cell vertices have 6 supports */
1601     for (c = cStart; c < cMax; ++c) {
1602       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
1603 
1604       ierr = DMPlexSetSupportSize(rdm, newp, 6);CHKERRQ(ierr);
1605     }
1606     break;
1607   default:
1608     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
1609   }
1610   PetscFunctionReturn(0);
1611 }
1612 
1613 static PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
1614 {
1615   const PetscInt *faces, cellInd[4] = {0, 1, 2, 3};
1616   PetscInt        cStart,    cEnd,    cMax,    vStart,    vEnd, vMax, fStart,    fEnd,    fMax,    eStart,    eEnd,    eMax;
1617   PetscInt        cStartNew, cEndNew, cMaxNew, vStartNew, vEndNew,    fStartNew, fEndNew, fMaxNew, eStartNew, eEndNew, eMaxNew;
1618   PetscInt        depth, maxSupportSize, *supportRef, c, f, e, v, r;
1619 #if defined(PETSC_USE_DEBUG)
1620   PetscInt        p;
1621 #endif
1622   PetscErrorCode  ierr;
1623 
1624   PetscFunctionBegin;
1625   if (!refiner) PetscFunctionReturn(0);
1626   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1627   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
1628   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
1629   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1630   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
1631   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
1632   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
1633   ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr);
1634   switch (refiner) {
1635   case REFINER_SIMPLEX_1D:
1636     /* Max support size of refined mesh is 2 */
1637     ierr = PetscMalloc1(2, &supportRef);CHKERRQ(ierr);
1638     /* All cells have 2 vertices */
1639     for (c = cStart; c < cEnd; ++c) {
1640       const PetscInt  newv = vStartNew + (vEnd - vStart) + (c - cStart);
1641 
1642       for (r = 0; r < 2; ++r) {
1643         const PetscInt newp = cStartNew + (c - cStart)*2 + r;
1644         const PetscInt *cone;
1645         PetscInt        coneNew[2];
1646 
1647         ierr             = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1648         coneNew[0]       = vStartNew + (cone[0] - vStart);
1649         coneNew[1]       = vStartNew + (cone[1] - vStart);
1650         coneNew[(r+1)%2] = newv;
1651         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1652 #if defined(PETSC_USE_DEBUG)
1653         if ((newp < cStartNew) || (newp >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp, cStartNew, cEndNew);
1654         for (p = 0; p < 2; ++p) {
1655           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
1656         }
1657 #endif
1658       }
1659     }
1660     /* Old vertices have identical supports */
1661     for (v = vStart; v < vEnd; ++v) {
1662       const PetscInt  newp = vStartNew + (v - vStart);
1663       const PetscInt *support, *cone;
1664       PetscInt        size, s;
1665 
1666       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
1667       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
1668       for (s = 0; s < size; ++s) {
1669         PetscInt r = 0;
1670 
1671         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1672         if (cone[1] == v) r = 1;
1673         supportRef[s] = cStartNew + (support[s] - cStart)*2 + r;
1674       }
1675       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1676 #if defined(PETSC_USE_DEBUG)
1677       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
1678       for (p = 0; p < size; ++p) {
1679         if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
1680       }
1681 #endif
1682     }
1683     /* Cell vertices have support of 2 cells */
1684     for (c = cStart; c < cEnd; ++c) {
1685       const PetscInt  newp = vStartNew + (vEnd - vStart) + (c - cStart);
1686 
1687       supportRef[0] = cStartNew + (c - cStart)*2 + 0;
1688       supportRef[1] = cStartNew + (c - cStart)*2 + 1;
1689       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1690 #if defined(PETSC_USE_DEBUG)
1691       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
1692       for (p = 0; p < 2; ++p) {
1693         if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
1694       }
1695 #endif
1696     }
1697     ierr = PetscFree(supportRef);CHKERRQ(ierr);
1698     break;
1699   case REFINER_SIMPLEX_2D:
1700     /*
1701      2
1702      |\
1703      | \
1704      |  \
1705      |   \
1706      | C  \
1707      |     \
1708      |      \
1709      2---1---1
1710      |\  D  / \
1711      | 2   0   \
1712      |A \ /  B  \
1713      0---0-------1
1714      */
1715     /* All cells have 3 faces */
1716     for (c = cStart; c < cEnd; ++c) {
1717       const PetscInt  newp = cStartNew + (c - cStart)*4;
1718       const PetscInt *cone, *ornt;
1719       PetscInt        coneNew[3], orntNew[3];
1720 
1721       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1722       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1723       /* A triangle */
1724       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1725       orntNew[0] = ornt[0];
1726       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
1727       orntNew[1] = -2;
1728       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1729       orntNew[2] = ornt[2];
1730       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1731       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1732 #if defined(PETSC_USE_DEBUG)
1733       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
1734       for (p = 0; p < 3; ++p) {
1735         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
1736       }
1737 #endif
1738       /* B triangle */
1739       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1740       orntNew[0] = ornt[0];
1741       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1742       orntNew[1] = ornt[1];
1743       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
1744       orntNew[2] = -2;
1745       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1746       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1747 #if defined(PETSC_USE_DEBUG)
1748       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
1749       for (p = 0; p < 3; ++p) {
1750         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
1751       }
1752 #endif
1753       /* C triangle */
1754       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
1755       orntNew[0] = -2;
1756       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1757       orntNew[1] = ornt[1];
1758       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1759       orntNew[2] = ornt[2];
1760       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1761       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1762 #if defined(PETSC_USE_DEBUG)
1763       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
1764       for (p = 0; p < 3; ++p) {
1765         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
1766       }
1767 #endif
1768       /* D triangle */
1769       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
1770       orntNew[0] = 0;
1771       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
1772       orntNew[1] = 0;
1773       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
1774       orntNew[2] = 0;
1775       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
1776       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
1777 #if defined(PETSC_USE_DEBUG)
1778       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
1779       for (p = 0; p < 3; ++p) {
1780         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
1781       }
1782 #endif
1783     }
1784     /* Split faces have 2 vertices and the same cells as the parent */
1785     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
1786     ierr = PetscMalloc1(2 + maxSupportSize*2, &supportRef);CHKERRQ(ierr);
1787     for (f = fStart; f < fEnd; ++f) {
1788       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
1789 
1790       for (r = 0; r < 2; ++r) {
1791         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
1792         const PetscInt *cone, *ornt, *support;
1793         PetscInt        coneNew[2], coneSize, c, supportSize, s;
1794 
1795         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1796         coneNew[0]       = vStartNew + (cone[0] - vStart);
1797         coneNew[1]       = vStartNew + (cone[1] - vStart);
1798         coneNew[(r+1)%2] = newv;
1799         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1800 #if defined(PETSC_USE_DEBUG)
1801         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
1802         for (p = 0; p < 2; ++p) {
1803           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
1804         }
1805 #endif
1806         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1807         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1808         for (s = 0; s < supportSize; ++s) {
1809           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1810           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1811           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1812           for (c = 0; c < coneSize; ++c) {
1813             if (cone[c] == f) break;
1814           }
1815           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
1816         }
1817         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1818 #if defined(PETSC_USE_DEBUG)
1819         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
1820         for (p = 0; p < supportSize; ++p) {
1821           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
1822         }
1823 #endif
1824       }
1825     }
1826     /* Interior faces have 2 vertices and 2 cells */
1827     for (c = cStart; c < cEnd; ++c) {
1828       const PetscInt *cone;
1829 
1830       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1831       for (r = 0; r < 3; ++r) {
1832         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
1833         PetscInt       coneNew[2];
1834         PetscInt       supportNew[2];
1835 
1836         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
1837         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
1838         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1839 #if defined(PETSC_USE_DEBUG)
1840         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
1841         for (p = 0; p < 2; ++p) {
1842           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
1843         }
1844 #endif
1845         supportNew[0] = (c - cStart)*4 + (r+1)%3;
1846         supportNew[1] = (c - cStart)*4 + 3;
1847         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1848 #if defined(PETSC_USE_DEBUG)
1849         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
1850         for (p = 0; p < 2; ++p) {
1851           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
1852         }
1853 #endif
1854       }
1855     }
1856     /* Old vertices have identical supports */
1857     for (v = vStart; v < vEnd; ++v) {
1858       const PetscInt  newp = vStartNew + (v - vStart);
1859       const PetscInt *support, *cone;
1860       PetscInt        size, s;
1861 
1862       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
1863       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
1864       for (s = 0; s < size; ++s) {
1865         PetscInt r = 0;
1866 
1867         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1868         if (cone[1] == v) r = 1;
1869         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1870       }
1871       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1872 #if defined(PETSC_USE_DEBUG)
1873       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
1874       for (p = 0; p < size; ++p) {
1875         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
1876       }
1877 #endif
1878     }
1879     /* Face vertices have 2 + cells*2 supports */
1880     for (f = fStart; f < fEnd; ++f) {
1881       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
1882       const PetscInt *cone, *support;
1883       PetscInt        size, s;
1884 
1885       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1886       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1887       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1888       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1889       for (s = 0; s < size; ++s) {
1890         PetscInt r = 0;
1891 
1892         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1893         if      (cone[1] == f) r = 1;
1894         else if (cone[2] == f) r = 2;
1895         supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
1896         supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
1897       }
1898       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1899 #if defined(PETSC_USE_DEBUG)
1900       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
1901       for (p = 0; p < 2+size*2; ++p) {
1902         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
1903       }
1904 #endif
1905     }
1906     ierr = PetscFree(supportRef);CHKERRQ(ierr);
1907     break;
1908   case REFINER_SIMPLEX_TO_HEX_2D:
1909     /*
1910      2
1911      |\
1912      | \
1913      |  \
1914      |   \
1915      | C  \
1916      |     \
1917      2      1
1918      |\    / \
1919      | 2  1   \
1920      |  \/     \
1921      |   |      \
1922      |A  |   B   \
1923      |   0        \
1924      |   |         \
1925      0---0----------1
1926      */
1927     /* All cells have 4 faces */
1928     for (c = cStart; c < cEnd; ++c) {
1929       const PetscInt  newp = cStartNew + (c - cStart)*3;
1930       const PetscInt *cone, *ornt;
1931       PetscInt        coneNew[4], orntNew[4];
1932 
1933       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1934       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1935       /* A quad */
1936       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1937       orntNew[0] = ornt[0];
1938       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
1939       orntNew[1] = 0;
1940       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
1941       orntNew[2] = -2;
1942       coneNew[3] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1943       orntNew[3] = ornt[2];
1944       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1945       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1946 #if defined(PETSC_USE_DEBUG)
1947       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
1948       for (p = 0; p < 4; ++p) {
1949         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
1950       }
1951 #endif
1952       /* B quad */
1953       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1954       orntNew[0] = ornt[0];
1955       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1956       orntNew[1] = ornt[1];
1957       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
1958       orntNew[2] = 0;
1959       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
1960       orntNew[3] = -2;
1961       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1962       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1963 #if defined(PETSC_USE_DEBUG)
1964       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
1965       for (p = 0; p < 4; ++p) {
1966         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
1967       }
1968 #endif
1969       /* C quad */
1970       coneNew[0] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1971       orntNew[0] = ornt[1];
1972       coneNew[1] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1973       orntNew[1] = ornt[2];
1974       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
1975       orntNew[2] = 0;
1976       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
1977       orntNew[3] = -2;
1978       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1979       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1980 #if defined(PETSC_USE_DEBUG)
1981       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
1982       for (p = 0; p < 4; ++p) {
1983         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
1984       }
1985 #endif
1986     }
1987     /* Split faces have 2 vertices and the same cells as the parent */
1988     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
1989     ierr = PetscMalloc1(2 + maxSupportSize*2, &supportRef);CHKERRQ(ierr);
1990     for (f = fStart; f < fEnd; ++f) {
1991       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
1992 
1993       for (r = 0; r < 2; ++r) {
1994         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
1995         const PetscInt *cone, *ornt, *support;
1996         PetscInt        coneNew[2], coneSize, c, supportSize, s;
1997 
1998         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1999         coneNew[0]       = vStartNew + (cone[0] - vStart);
2000         coneNew[1]       = vStartNew + (cone[1] - vStart);
2001         coneNew[(r+1)%2] = newv;
2002         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2003 #if defined(PETSC_USE_DEBUG)
2004         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2005         for (p = 0; p < 2; ++p) {
2006           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2007         }
2008 #endif
2009         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
2010         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2011         for (s = 0; s < supportSize; ++s) {
2012           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2013           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2014           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
2015           for (c = 0; c < coneSize; ++c) {
2016             if (cone[c] == f) break;
2017           }
2018           supportRef[s] = cStartNew + (support[s] - cStart)*3 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
2019         }
2020         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2021 #if defined(PETSC_USE_DEBUG)
2022         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2023         for (p = 0; p < supportSize; ++p) {
2024           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
2025         }
2026 #endif
2027       }
2028     }
2029     /* Interior faces have 2 vertices and 2 cells */
2030     for (c = cStart; c < cEnd; ++c) {
2031       const PetscInt *cone;
2032 
2033       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2034       for (r = 0; r < 3; ++r) {
2035         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
2036         PetscInt       coneNew[2];
2037         PetscInt       supportNew[2];
2038 
2039         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2040         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
2041         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2042 #if defined(PETSC_USE_DEBUG)
2043         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2044         for (p = 0; p < 2; ++p) {
2045           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2046         }
2047 #endif
2048         supportNew[0] = (c - cStart)*3 + r%3;
2049         supportNew[1] = (c - cStart)*3 + (r+1)%3;
2050         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2051 #if defined(PETSC_USE_DEBUG)
2052         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2053         for (p = 0; p < 2; ++p) {
2054           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
2055         }
2056 #endif
2057       }
2058     }
2059     /* Old vertices have identical supports */
2060     for (v = vStart; v < vEnd; ++v) {
2061       const PetscInt  newp = vStartNew + (v - vStart);
2062       const PetscInt *support, *cone;
2063       PetscInt        size, s;
2064 
2065       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
2066       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
2067       for (s = 0; s < size; ++s) {
2068         PetscInt r = 0;
2069 
2070         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2071         if (cone[1] == v) r = 1;
2072         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
2073       }
2074       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2075 #if defined(PETSC_USE_DEBUG)
2076       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2077       for (p = 0; p < size; ++p) {
2078         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2079       }
2080 #endif
2081     }
2082     /* Split-face vertices have cells + 2 supports */
2083     for (f = fStart; f < fEnd; ++f) {
2084       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
2085       const PetscInt *cone, *support;
2086       PetscInt        size, s;
2087 
2088       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
2089       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2090       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2091       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2092       for (s = 0; s < size; ++s) {
2093         PetscInt r = 0;
2094 
2095         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2096         if      (cone[1] == f) r = 1;
2097         else if (cone[2] == f) r = 2;
2098         supportRef[2+s+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
2099       }
2100       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2101 #if defined(PETSC_USE_DEBUG)
2102       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2103       for (p = 0; p < 2+size; ++p) {
2104         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2105       }
2106 #endif
2107     }
2108     /* Interior vertices have 3 supports */
2109     for (c = cStart; c < cEnd; ++c) {
2110       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;
2111 
2112       supportRef[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
2113       supportRef[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
2114       supportRef[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
2115       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2116     }
2117     ierr = PetscFree(supportRef);CHKERRQ(ierr);
2118     break;
2119   case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
2120     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
2121     cMax = PetscMin(cEnd, cMax);
2122     for (c = cStart; c < cMax; ++c) {
2123       const PetscInt  newp = cStartNew + (c - cStart)*3;
2124       const PetscInt *cone, *ornt;
2125       PetscInt        coneNew[4], orntNew[4];
2126 
2127       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2128       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2129       /* A quad */
2130       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2131       orntNew[0] = ornt[0];
2132       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
2133       orntNew[1] = 0;
2134       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
2135       orntNew[2] = -2;
2136       coneNew[3] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2137       orntNew[3] = ornt[2];
2138       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
2139       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
2140 #if defined(PETSC_USE_DEBUG)
2141       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
2142       for (p = 0; p < 4; ++p) {
2143         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2144       }
2145 #endif
2146       /* B quad */
2147       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2148       orntNew[0] = ornt[0];
2149       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2150       orntNew[1] = ornt[1];
2151       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
2152       orntNew[2] = 0;
2153       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
2154       orntNew[3] = -2;
2155       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
2156       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
2157 #if defined(PETSC_USE_DEBUG)
2158       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
2159       for (p = 0; p < 4; ++p) {
2160         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2161       }
2162 #endif
2163       /* C quad */
2164       coneNew[0] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2165       orntNew[0] = ornt[1];
2166       coneNew[1] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2167       orntNew[1] = ornt[2];
2168       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
2169       orntNew[2] = 0;
2170       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
2171       orntNew[3] = -2;
2172       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
2173       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
2174 #if defined(PETSC_USE_DEBUG)
2175       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
2176       for (p = 0; p < 4; ++p) {
2177         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2178       }
2179 #endif
2180     }
2181     /*
2182      2---------1---------3
2183      |         |         |
2184      |    D    1    C    |
2185      |         |         |
2186      2----2----0----3----3
2187      |         |         |
2188      |    A    0    B    |
2189      |         |         |
2190      0---------0---------1
2191      */
2192     /* Parent cells are input as prisms but children are quads, since the mesh is no longer hybrid */
2193     for (c = cMax; c < cEnd; ++c) {
2194       const PetscInt  newp  = cStartNew + (cMax - cStart)*3 + (c - cMax)*4;
2195       const PetscInt  newpt = (cMax - cStart)*3 + (c - cMax)*4;
2196       const PetscInt *cone, *ornt;
2197       PetscInt        coneNew[4], orntNew[4];
2198 
2199       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2200       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2201       /* A quad */
2202       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2203       orntNew[0] = ornt[0];
2204       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + newpt + 0;
2205       orntNew[1] = 0;
2206       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + newpt + 2;
2207       orntNew[2] = -2;
2208       coneNew[3] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2209       orntNew[3] = ornt[2] < 0 ? 0 : -2;
2210       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
2211       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
2212 #if defined(PETSC_USE_DEBUG)
2213       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
2214       for (p = 0; p < 4; ++p) {
2215         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2216       }
2217 #endif
2218       /* B quad */
2219       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2220       orntNew[0] = ornt[0];
2221       coneNew[1] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
2222       orntNew[1] = ornt[3];
2223       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + newpt + 3;
2224       orntNew[2] = 0;
2225       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + newpt + 0;
2226       orntNew[3] = -2;
2227       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
2228       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
2229 #if defined(PETSC_USE_DEBUG)
2230       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
2231       for (p = 0; p < 4; ++p) {
2232         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2233       }
2234 #endif
2235       /* C quad */
2236       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + newpt + 3;
2237       orntNew[0] = -2;
2238       coneNew[1] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
2239       orntNew[1] = ornt[3];
2240       coneNew[2] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2241       orntNew[2] = ornt[1] < 0 ? 0 : -2;
2242       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + newpt + 1;
2243       orntNew[3] = 0;
2244       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
2245       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
2246 #if defined(PETSC_USE_DEBUG)
2247       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
2248       for (p = 0; p < 4; ++p) {
2249         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2250       }
2251 #endif
2252       /* D quad */
2253       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + newpt + 2;
2254       orntNew[0] = 0;
2255       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + newpt + 1;
2256       orntNew[1] = -2;
2257       coneNew[2] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2258       orntNew[2] = ornt[1] < 0 ? 0 : -2;
2259       coneNew[3] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2260       orntNew[3] = ornt[2] < 0 ? 0 : -2;
2261       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
2262       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
2263 #if defined(PETSC_USE_DEBUG)
2264       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
2265       for (p = 0; p < 4; ++p) {
2266         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2267       }
2268 #endif
2269     }
2270     /* Split faces have 2 vertices and the same cells as the parent */
2271     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
2272     ierr = PetscMalloc1(2 + maxSupportSize*2, &supportRef);CHKERRQ(ierr);
2273     for (f = fStart; f < fEnd; ++f) {
2274       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
2275 
2276       for (r = 0; r < 2; ++r) {
2277         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
2278         const PetscInt *cone, *ornt, *support;
2279         PetscInt        coneNew[2], coneSize, c, supportSize, s;
2280 
2281         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
2282         coneNew[0]       = vStartNew + (cone[0] - vStart);
2283         coneNew[1]       = vStartNew + (cone[1] - vStart);
2284         coneNew[(r+1)%2] = newv;
2285         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2286 #if defined(PETSC_USE_DEBUG)
2287         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2288         for (p = 0; p < 2; ++p) {
2289           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2290         }
2291 #endif
2292         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
2293         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2294         for (s = 0; s < supportSize; ++s) {
2295           const PetscInt p2q[4][2] = { {0, 1},
2296                                        {3, 2},
2297                                        {0, 3},
2298                                        {1, 2} };
2299 
2300           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2301           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2302           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
2303           for (c = 0; c < coneSize; ++c) {
2304             if (cone[c] == f) break;
2305           }
2306           if (coneSize == 3)      supportRef[s] = cStartNew + (support[s] - cStart)*3 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
2307           else if (coneSize == 4) supportRef[s] = cStartNew + (cMax - cStart)*3 + (support[s] - cMax)*4 + (ornt[c] < 0 ? p2q[c][(r+1)%2] : p2q[c][r]);
2308           else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected cone size %D", coneSize);
2309         }
2310         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2311 #if defined(PETSC_USE_DEBUG)
2312         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2313         for (p = 0; p < supportSize; ++p) {
2314           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
2315         }
2316 #endif
2317       }
2318     }
2319     /* Interior faces have 2 vertices and 2 cells */
2320     for (c = cStart; c < cMax; ++c) {
2321       const PetscInt *cone;
2322 
2323       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2324       for (r = 0; r < 3; ++r) {
2325         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
2326         PetscInt       coneNew[2];
2327         PetscInt       supportNew[2];
2328 
2329         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2330         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
2331         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2332 #if defined(PETSC_USE_DEBUG)
2333         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2334         for (p = 0; p < 2; ++p) {
2335           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2336         }
2337 #endif
2338         supportNew[0] = (c - cStart)*3 + r%3;
2339         supportNew[1] = (c - cStart)*3 + (r+1)%3;
2340         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2341 #if defined(PETSC_USE_DEBUG)
2342         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2343         for (p = 0; p < 2; ++p) {
2344           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
2345         }
2346 #endif
2347       }
2348     }
2349     /* Hybrid interior faces have 2 vertices and 2 cells */
2350     for (c = cMax; c < cEnd; ++c) {
2351       const PetscInt *cone;
2352       PetscInt        coneNew[2], supportNew[2];
2353 
2354       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2355       for (r = 0; r < 4; ++r) {
2356         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (c - cMax)*4 + r;
2357 
2358         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2359         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (cMax - cStart) + (c - cMax);
2360 	ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2361 #if defined(PETSC_USE_DEBUG)
2362         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2363         for (p = 0; p < 2; ++p) {
2364           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2365         }
2366 #endif
2367         if (r==0) {
2368           supportNew[0] = (cMax - cStart)*3 + (c - cMax)*4 + 0;
2369           supportNew[1] = (cMax - cStart)*3 + (c - cMax)*4 + 1;
2370         } else if (r==1) {
2371           supportNew[0] = (cMax - cStart)*3 + (c - cMax)*4 + 2;
2372           supportNew[1] = (cMax - cStart)*3 + (c - cMax)*4 + 3;
2373         } else if (r==2) {
2374           supportNew[0] = (cMax - cStart)*3 + (c - cMax)*4 + 0;
2375           supportNew[1] = (cMax - cStart)*3 + (c - cMax)*4 + 3;
2376         } else {
2377           supportNew[0] = (cMax - cStart)*3 + (c - cMax)*4 + 1;
2378           supportNew[1] = (cMax - cStart)*3 + (c - cMax)*4 + 2;
2379         }
2380         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2381 #if defined(PETSC_USE_DEBUG)
2382         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2383         for (p = 0; p < 2; ++p) {
2384           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
2385         }
2386 #endif
2387       }
2388     }
2389     /* Old vertices have identical supports */
2390     for (v = vStart; v < vEnd; ++v) {
2391       const PetscInt  newp = vStartNew + (v - vStart);
2392       const PetscInt *support, *cone;
2393       PetscInt        size, s;
2394 
2395       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
2396       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
2397       for (s = 0; s < size; ++s) {
2398         PetscInt r = 0;
2399 
2400         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2401         if (cone[1] == v) r = 1;
2402         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
2403       }
2404       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2405 #if defined(PETSC_USE_DEBUG)
2406       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2407       for (p = 0; p < size; ++p) {
2408         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2409       }
2410 #endif
2411     }
2412     /* Split-face vertices have cells + 2 supports */
2413     for (f = fStart; f < fEnd; ++f) {
2414       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
2415       const PetscInt *cone, *support;
2416       PetscInt        size, s;
2417 
2418       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
2419       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2420       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2421       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2422       for (s = 0; s < size; ++s) {
2423         PetscInt r = 0, coneSize;
2424 
2425         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2426         ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2427         if (coneSize == 3) {
2428           if      (cone[1] == f) r = 1;
2429           else if (cone[2] == f) r = 2;
2430           supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
2431         } else if (coneSize == 4) {
2432           if      (cone[1] == f) r = 1;
2433           else if (cone[2] == f) r = 2;
2434           else if (cone[3] == f) r = 3;
2435           supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (support[s] - cMax)*4 + r;
2436         } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected cone size %D", coneSize);
2437       }
2438       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2439 #if defined(PETSC_USE_DEBUG)
2440       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2441       for (p = 0; p < 2+size; ++p) {
2442         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2443       }
2444 #endif
2445     }
2446     /* Interior vertices have 3 supports */
2447     for (c = cStart; c < cMax; ++c) {
2448       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;
2449 
2450       supportRef[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
2451       supportRef[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
2452       supportRef[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
2453       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2454     }
2455     /* Hybrid interior vertices have 4 supports */
2456     for (c = cMax; c < cEnd; ++c) {
2457       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;
2458 
2459       supportRef[0] = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (c - cMax)*4 + 0;
2460       supportRef[1] = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (c - cMax)*4 + 1;
2461       supportRef[2] = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (c - cMax)*4 + 2;
2462       supportRef[3] = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (c - cMax)*4 + 3;
2463       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2464     }
2465     ierr = PetscFree(supportRef);CHKERRQ(ierr);
2466     break;
2467   case REFINER_HEX_2D:
2468     /*
2469      3---------2---------2
2470      |         |         |
2471      |    D    2    C    |
2472      |         |         |
2473      3----3----0----1----1
2474      |         |         |
2475      |    A    0    B    |
2476      |         |         |
2477      0---------0---------1
2478      */
2479     /* All cells have 4 faces */
2480     for (c = cStart; c < cEnd; ++c) {
2481       const PetscInt  newp = (c - cStart)*4;
2482       const PetscInt *cone, *ornt;
2483       PetscInt        coneNew[4], orntNew[4];
2484 
2485       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2486       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2487       /* A quad */
2488       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2489       orntNew[0] = ornt[0];
2490       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
2491       orntNew[1] = 0;
2492       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
2493       orntNew[2] = -2;
2494       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
2495       orntNew[3] = ornt[3];
2496       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
2497       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
2498 #if defined(PETSC_USE_DEBUG)
2499       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
2500       for (p = 0; p < 4; ++p) {
2501         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2502       }
2503 #endif
2504       /* B quad */
2505       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2506       orntNew[0] = ornt[0];
2507       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2508       orntNew[1] = ornt[1];
2509       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
2510       orntNew[2] = -2;
2511       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
2512       orntNew[3] = -2;
2513       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
2514       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
2515 #if defined(PETSC_USE_DEBUG)
2516       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
2517       for (p = 0; p < 4; ++p) {
2518         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2519       }
2520 #endif
2521       /* C quad */
2522       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
2523       orntNew[0] = 0;
2524       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2525       orntNew[1] = ornt[1];
2526       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2527       orntNew[2] = ornt[2];
2528       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
2529       orntNew[3] = -2;
2530       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
2531       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
2532 #if defined(PETSC_USE_DEBUG)
2533       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
2534       for (p = 0; p < 4; ++p) {
2535         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2536       }
2537 #endif
2538       /* D quad */
2539       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
2540       orntNew[0] = 0;
2541       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
2542       orntNew[1] = 0;
2543       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2544       orntNew[2] = ornt[2];
2545       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
2546       orntNew[3] = ornt[3];
2547       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
2548       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
2549 #if defined(PETSC_USE_DEBUG)
2550       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
2551       for (p = 0; p < 4; ++p) {
2552         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2553       }
2554 #endif
2555     }
2556     /* Split faces have 2 vertices and the same cells as the parent */
2557     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
2558     ierr = PetscMalloc1(2 + maxSupportSize*2, &supportRef);CHKERRQ(ierr);
2559     for (f = fStart; f < fEnd; ++f) {
2560       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
2561 
2562       for (r = 0; r < 2; ++r) {
2563         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
2564         const PetscInt *cone, *ornt, *support;
2565         PetscInt        coneNew[2], coneSize, c, supportSize, s;
2566 
2567         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
2568         coneNew[0]       = vStartNew + (cone[0] - vStart);
2569         coneNew[1]       = vStartNew + (cone[1] - vStart);
2570         coneNew[(r+1)%2] = newv;
2571         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2572 #if defined(PETSC_USE_DEBUG)
2573         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2574         for (p = 0; p < 2; ++p) {
2575           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2576         }
2577 #endif
2578         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
2579         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2580         for (s = 0; s < supportSize; ++s) {
2581           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2582           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2583           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
2584           for (c = 0; c < coneSize; ++c) {
2585             if (cone[c] == f) break;
2586           }
2587           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
2588         }
2589         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2590 #if defined(PETSC_USE_DEBUG)
2591         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2592         for (p = 0; p < supportSize; ++p) {
2593           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
2594         }
2595 #endif
2596       }
2597     }
2598     /* Interior faces have 2 vertices and 2 cells */
2599     for (c = cStart; c < cEnd; ++c) {
2600       const PetscInt *cone;
2601       PetscInt        coneNew[2], supportNew[2];
2602 
2603       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2604       for (r = 0; r < 4; ++r) {
2605         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
2606 
2607 	if (r==1 || r==2) {
2608           coneNew[0] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
2609           coneNew[1] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2610 	} else {
2611           coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2612           coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
2613 	}
2614 	ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2615 #if defined(PETSC_USE_DEBUG)
2616         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2617         for (p = 0; p < 2; ++p) {
2618           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2619         }
2620 #endif
2621         supportNew[0] = (c - cStart)*4 + r;
2622         supportNew[1] = (c - cStart)*4 + (r+1)%4;
2623         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2624 #if defined(PETSC_USE_DEBUG)
2625         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2626         for (p = 0; p < 2; ++p) {
2627           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
2628         }
2629 #endif
2630       }
2631     }
2632     /* Old vertices have identical supports */
2633     for (v = vStart; v < vEnd; ++v) {
2634       const PetscInt  newp = vStartNew + (v - vStart);
2635       const PetscInt *support, *cone;
2636       PetscInt        size, s;
2637 
2638       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
2639       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
2640       for (s = 0; s < size; ++s) {
2641         PetscInt r = 0;
2642 
2643         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2644         if (cone[1] == v) r = 1;
2645         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
2646       }
2647       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2648 #if defined(PETSC_USE_DEBUG)
2649       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2650       for (p = 0; p < size; ++p) {
2651         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2652       }
2653 #endif
2654     }
2655     /* Face vertices have 2 + cells supports */
2656     for (f = fStart; f < fEnd; ++f) {
2657       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
2658       const PetscInt *cone, *support;
2659       PetscInt        size, s;
2660 
2661       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
2662       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2663       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2664       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2665       for (s = 0; s < size; ++s) {
2666         PetscInt r = 0;
2667 
2668         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2669         if      (cone[1] == f) r = 1;
2670         else if (cone[2] == f) r = 2;
2671         else if (cone[3] == f) r = 3;
2672         supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r;
2673       }
2674       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2675 #if defined(PETSC_USE_DEBUG)
2676       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2677       for (p = 0; p < 2+size; ++p) {
2678         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2679       }
2680 #endif
2681     }
2682     /* Cell vertices have 4 supports */
2683     for (c = cStart; c < cEnd; ++c) {
2684       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
2685       PetscInt       supportNew[4];
2686 
2687       for (r = 0; r < 4; ++r) {
2688         supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
2689       }
2690       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2691     }
2692     ierr = PetscFree(supportRef);CHKERRQ(ierr);
2693     break;
2694   case REFINER_HYBRID_SIMPLEX_2D:
2695     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
2696     cMax = PetscMin(cEnd, cMax);
2697     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
2698     fMax = PetscMin(fEnd, fMax);
2699     ierr = DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, NULL, NULL);CHKERRQ(ierr);
2700     /* Interior cells have 3 faces */
2701     for (c = cStart; c < cMax; ++c) {
2702       const PetscInt  newp = cStartNew + (c - cStart)*4;
2703       const PetscInt *cone, *ornt;
2704       PetscInt        coneNew[3], orntNew[3];
2705 
2706       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2707       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2708       /* A triangle */
2709       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2710       orntNew[0] = ornt[0];
2711       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
2712       orntNew[1] = -2;
2713       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2714       orntNew[2] = ornt[2];
2715       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
2716       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
2717 #if defined(PETSC_USE_DEBUG)
2718       if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+0, cStartNew, cMaxNew);
2719       for (p = 0; p < 3; ++p) {
2720         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
2721       }
2722 #endif
2723       /* B triangle */
2724       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2725       orntNew[0] = ornt[0];
2726       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2727       orntNew[1] = ornt[1];
2728       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
2729       orntNew[2] = -2;
2730       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
2731       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
2732 #if defined(PETSC_USE_DEBUG)
2733       if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+1, cStartNew, cMaxNew);
2734       for (p = 0; p < 3; ++p) {
2735         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
2736       }
2737 #endif
2738       /* C triangle */
2739       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
2740       orntNew[0] = -2;
2741       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2742       orntNew[1] = ornt[1];
2743       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2744       orntNew[2] = ornt[2];
2745       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
2746       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
2747 #if defined(PETSC_USE_DEBUG)
2748       if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+2, cStartNew, cMaxNew);
2749       for (p = 0; p < 3; ++p) {
2750         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
2751       }
2752 #endif
2753       /* D triangle */
2754       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
2755       orntNew[0] = 0;
2756       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
2757       orntNew[1] = 0;
2758       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
2759       orntNew[2] = 0;
2760       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
2761       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
2762 #if defined(PETSC_USE_DEBUG)
2763       if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+3, cStartNew, cMaxNew);
2764       for (p = 0; p < 3; ++p) {
2765         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
2766       }
2767 #endif
2768     }
2769     /*
2770      2----3----3
2771      |         |
2772      |    B    |
2773      |         |
2774      0----4--- 1
2775      |         |
2776      |    A    |
2777      |         |
2778      0----2----1
2779      */
2780     /* Hybrid cells have 4 faces */
2781     for (c = cMax; c < cEnd; ++c) {
2782       const PetscInt  newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
2783       const PetscInt *cone, *ornt;
2784       PetscInt        coneNew[4], orntNew[4], r;
2785 
2786       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2787       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2788       r    = (ornt[0] < 0 ? 1 : 0);
2789       /* A quad */
2790       coneNew[0]   = fStartNew + (cone[0] - fStart)*2 + r;
2791       orntNew[0]   = ornt[0];
2792       coneNew[1]   = fStartNew + (cone[1] - fStart)*2 + r;
2793       orntNew[1]   = ornt[1];
2794       coneNew[2+r] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[2+r] - fMax);
2795       orntNew[2+r] = 0;
2796       coneNew[3-r] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
2797       orntNew[3-r] = 0;
2798       ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
2799       ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
2800 #if defined(PETSC_USE_DEBUG)
2801       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
2802       for (p = 0; p < 4; ++p) {
2803         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2804       }
2805 #endif
2806       /* B quad */
2807       coneNew[0]   = fStartNew + (cone[0] - fStart)*2 + 1-r;
2808       orntNew[0]   = ornt[0];
2809       coneNew[1]   = fStartNew + (cone[1] - fStart)*2 + 1-r;
2810       orntNew[1]   = ornt[1];
2811       coneNew[2+r] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
2812       orntNew[2+r] = 0;
2813       coneNew[3-r] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[3-r] - fMax);
2814       orntNew[3-r] = 0;
2815       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
2816       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
2817 #if defined(PETSC_USE_DEBUG)
2818       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
2819       for (p = 0; p < 4; ++p) {
2820         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2821       }
2822 #endif
2823     }
2824     /* Interior split faces have 2 vertices and the same cells as the parent */
2825     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
2826     ierr = PetscMalloc1(2 + maxSupportSize*2, &supportRef);CHKERRQ(ierr);
2827     for (f = fStart; f < fMax; ++f) {
2828       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
2829 
2830       for (r = 0; r < 2; ++r) {
2831         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
2832         const PetscInt *cone, *ornt, *support;
2833         PetscInt        coneNew[2], coneSize, c, supportSize, s;
2834 
2835         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
2836         coneNew[0]       = vStartNew + (cone[0] - vStart);
2837         coneNew[1]       = vStartNew + (cone[1] - vStart);
2838         coneNew[(r+1)%2] = newv;
2839         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2840 #if defined(PETSC_USE_DEBUG)
2841         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2842         for (p = 0; p < 2; ++p) {
2843           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2844         }
2845 #endif
2846         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
2847         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2848         for (s = 0; s < supportSize; ++s) {
2849           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2850           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2851           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
2852           for (c = 0; c < coneSize; ++c) if (cone[c] == f) break;
2853           if (support[s] >= cMax) {
2854             supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + (ornt[c] < 0 ? 1-r : r);
2855           } else {
2856             supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
2857           }
2858         }
2859         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2860 #if defined(PETSC_USE_DEBUG)
2861         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2862         for (p = 0; p < supportSize; ++p) {
2863           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
2864         }
2865 #endif
2866       }
2867     }
2868     /* Interior cell faces have 2 vertices and 2 cells */
2869     for (c = cStart; c < cMax; ++c) {
2870       const PetscInt *cone;
2871 
2872       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2873       for (r = 0; r < 3; ++r) {
2874         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
2875         PetscInt       coneNew[2];
2876         PetscInt       supportNew[2];
2877 
2878         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
2879         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
2880         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2881 #if defined(PETSC_USE_DEBUG)
2882         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2883         for (p = 0; p < 2; ++p) {
2884           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2885         }
2886 #endif
2887         supportNew[0] = (c - cStart)*4 + (r+1)%3;
2888         supportNew[1] = (c - cStart)*4 + 3;
2889         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2890 #if defined(PETSC_USE_DEBUG)
2891         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2892         for (p = 0; p < 2; ++p) {
2893           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
2894         }
2895 #endif
2896       }
2897     }
2898     /* Interior hybrid faces have 2 vertices and the same cells */
2899     for (f = fMax; f < fEnd; ++f) {
2900       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
2901       const PetscInt *cone, *ornt;
2902       const PetscInt *support;
2903       PetscInt        coneNew[2];
2904       PetscInt        supportNew[2];
2905       PetscInt        size, s, r;
2906 
2907       ierr       = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
2908       coneNew[0] = vStartNew + (cone[0] - vStart);
2909       coneNew[1] = vStartNew + (cone[1] - vStart);
2910       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2911 #if defined(PETSC_USE_DEBUG)
2912       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2913       for (p = 0; p < 2; ++p) {
2914         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2915       }
2916 #endif
2917       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
2918       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2919       for (s = 0; s < size; ++s) {
2920         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2921         ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
2922         for (r = 0; r < 2; ++r) {
2923           if (cone[r+2] == f) break;
2924         }
2925         supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + (ornt[0] < 0 ? 1-r : r);
2926       }
2927       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2928 #if defined(PETSC_USE_DEBUG)
2929       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2930       for (p = 0; p < size; ++p) {
2931         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
2932       }
2933 #endif
2934     }
2935     /* Cell hybrid faces have 2 vertices and 2 cells */
2936     for (c = cMax; c < cEnd; ++c) {
2937       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
2938       const PetscInt *cone;
2939       PetscInt        coneNew[2];
2940       PetscInt        supportNew[2];
2941 
2942       ierr       = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2943       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
2944       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
2945       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2946 #if defined(PETSC_USE_DEBUG)
2947       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2948       for (p = 0; p < 2; ++p) {
2949         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2950       }
2951 #endif
2952       supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
2953       supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
2954       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2955 #if defined(PETSC_USE_DEBUG)
2956       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2957       for (p = 0; p < 2; ++p) {
2958         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
2959       }
2960 #endif
2961     }
2962     /* Old vertices have identical supports */
2963     for (v = vStart; v < vEnd; ++v) {
2964       const PetscInt  newp = vStartNew + (v - vStart);
2965       const PetscInt *support, *cone;
2966       PetscInt        size, s;
2967 
2968       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
2969       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
2970       for (s = 0; s < size; ++s) {
2971         if (support[s] >= fMax) {
2972           supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax);
2973         } else {
2974           PetscInt r = 0;
2975 
2976           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2977           if (cone[1] == v) r = 1;
2978           supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
2979         }
2980       }
2981       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2982 #if defined(PETSC_USE_DEBUG)
2983       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2984       for (p = 0; p < size; ++p) {
2985         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2986       }
2987 #endif
2988     }
2989     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
2990     for (f = fStart; f < fMax; ++f) {
2991       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
2992       const PetscInt *cone, *support;
2993       PetscInt        size, newSize = 2, s;
2994 
2995       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
2996       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2997       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2998       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2999       for (s = 0; s < size; ++s) {
3000         PetscInt r = 0;
3001 
3002         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3003         if (support[s] >= cMax) {
3004           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax);
3005 
3006           newSize += 1;
3007         } else {
3008           if      (cone[1] == f) r = 1;
3009           else if (cone[2] == f) r = 2;
3010           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
3011           supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r;
3012 
3013           newSize += 2;
3014         }
3015       }
3016       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3017 #if defined(PETSC_USE_DEBUG)
3018       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
3019       for (p = 0; p < newSize; ++p) {
3020         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
3021       }
3022 #endif
3023     }
3024     ierr = PetscFree(supportRef);CHKERRQ(ierr);
3025     break;
3026   case REFINER_HYBRID_HEX_2D:
3027     /* Hybrid Hex 2D */
3028     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
3029     cMax = PetscMin(cEnd, cMax);
3030     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
3031     fMax = PetscMin(fEnd, fMax);
3032     ierr = DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, NULL, NULL);CHKERRQ(ierr);
3033     /* Interior cells have 4 faces */
3034     for (c = cStart; c < cMax; ++c) {
3035       const PetscInt  newp = cStartNew + (c - cStart)*4;
3036       const PetscInt *cone, *ornt;
3037       PetscInt        coneNew[4], orntNew[4];
3038 
3039       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
3040       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
3041       /* A quad */
3042       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
3043       orntNew[0] = ornt[0];
3044       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 0;
3045       orntNew[1] = 0;
3046       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 3;
3047       orntNew[2] = -2;
3048       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
3049       orntNew[3] = ornt[3];
3050       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
3051       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
3052 #if defined(PETSC_USE_DEBUG)
3053       if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+0, cStartNew, cMaxNew);
3054       for (p = 0; p < 4; ++p) {
3055         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
3056       }
3057 #endif
3058       /* B quad */
3059       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
3060       orntNew[0] = ornt[0];
3061       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
3062       orntNew[1] = ornt[1];
3063       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 1;
3064       orntNew[2] = 0;
3065       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 0;
3066       orntNew[3] = -2;
3067       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
3068       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
3069 #if defined(PETSC_USE_DEBUG)
3070       if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+1, cStartNew, cMaxNew);
3071       for (p = 0; p < 4; ++p) {
3072         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
3073       }
3074 #endif
3075       /* C quad */
3076       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 1;
3077       orntNew[0] = -2;
3078       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
3079       orntNew[1] = ornt[1];
3080       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
3081       orntNew[2] = ornt[2];
3082       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 2;
3083       orntNew[3] = 0;
3084       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
3085       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
3086 #if defined(PETSC_USE_DEBUG)
3087       if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+2, cStartNew, cMaxNew);
3088       for (p = 0; p < 4; ++p) {
3089         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
3090       }
3091 #endif
3092       /* D quad */
3093       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 3;
3094       orntNew[0] = 0;
3095       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 2;
3096       orntNew[1] = -2;
3097       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
3098       orntNew[2] = ornt[2];
3099       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
3100       orntNew[3] = ornt[3];
3101       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
3102       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
3103 #if defined(PETSC_USE_DEBUG)
3104       if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+3, cStartNew, cMaxNew);
3105       for (p = 0; p < 4; ++p) {
3106         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
3107       }
3108 #endif
3109     }
3110     /*
3111      2----3----3
3112      |         |
3113      |    B    |
3114      |         |
3115      0----4--- 1
3116      |         |
3117      |    A    |
3118      |         |
3119      0----2----1
3120      */
3121     /* Hybrid cells have 4 faces */
3122     for (c = cMax; c < cEnd; ++c) {
3123       const PetscInt  newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
3124       const PetscInt *cone, *ornt;
3125       PetscInt        coneNew[4], orntNew[4];
3126 
3127       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
3128       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
3129       /* A quad */
3130       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
3131       orntNew[0] = ornt[0];
3132       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
3133       orntNew[1] = ornt[1];
3134       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*4 + (cone[2] - fMax);
3135       orntNew[2] = 0;
3136       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*4 + (fEnd    - fMax) + (c - cMax);
3137       orntNew[3] = 0;
3138       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
3139       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
3140 #if defined(PETSC_USE_DEBUG)
3141       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
3142       for (p = 0; p < 4; ++p) {
3143         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3144       }
3145 #endif
3146       /* B quad */
3147       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
3148       orntNew[0] = ornt[0];
3149       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
3150       orntNew[1] = ornt[1];
3151       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*4 + (fEnd    - fMax) + (c - cMax);
3152       orntNew[2] = 0;
3153       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*4 + (cone[3] - fMax);
3154       orntNew[3] = 0;
3155       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
3156       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
3157 #if defined(PETSC_USE_DEBUG)
3158       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
3159       for (p = 0; p < 4; ++p) {
3160         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3161       }
3162 #endif
3163     }
3164     /* Interior split faces have 2 vertices and the same cells as the parent */
3165     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
3166     ierr = PetscMalloc1(2 + maxSupportSize*2, &supportRef);CHKERRQ(ierr);
3167     for (f = fStart; f < fMax; ++f) {
3168       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
3169 
3170       for (r = 0; r < 2; ++r) {
3171         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
3172         const PetscInt *cone, *ornt, *support;
3173         PetscInt        coneNew[2], coneSize, c, supportSize, s;
3174 
3175         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
3176         coneNew[0]       = vStartNew + (cone[0] - vStart);
3177         coneNew[1]       = vStartNew + (cone[1] - vStart);
3178         coneNew[(r+1)%2] = newv;
3179         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3180 #if defined(PETSC_USE_DEBUG)
3181         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3182         for (p = 0; p < 2; ++p) {
3183           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3184         }
3185 #endif
3186         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
3187         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
3188         for (s = 0; s < supportSize; ++s) {
3189           if (support[s] >= cMax) {
3190             supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
3191           } else {
3192             ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
3193             ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3194             ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
3195             for (c = 0; c < coneSize; ++c) {
3196               if (cone[c] == f) break;
3197             }
3198             supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
3199           }
3200         }
3201         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3202 #if defined(PETSC_USE_DEBUG)
3203         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3204         for (p = 0; p < supportSize; ++p) {
3205           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
3206         }
3207 #endif
3208       }
3209     }
3210     /* Interior cell faces have 2 vertices and 2 cells */
3211     for (c = cStart; c < cMax; ++c) {
3212       const PetscInt *cone;
3213 
3214       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
3215       for (r = 0; r < 4; ++r) {
3216         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
3217         PetscInt       coneNew[2], supportNew[2];
3218 
3219         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
3220         coneNew[1] = vStartNew + (vEnd - vStart) + (fMax    - fStart) + (c - cStart);
3221         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3222 #if defined(PETSC_USE_DEBUG)
3223         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3224         for (p = 0; p < 2; ++p) {
3225           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3226         }
3227 #endif
3228         supportNew[0] = (c - cStart)*4 + r;
3229         supportNew[1] = (c - cStart)*4 + (r+1)%4;
3230         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3231 #if defined(PETSC_USE_DEBUG)
3232         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3233         for (p = 0; p < 2; ++p) {
3234           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3235         }
3236 #endif
3237       }
3238     }
3239     /* Hybrid faces have 2 vertices and the same cells */
3240     for (f = fMax; f < fEnd; ++f) {
3241       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (f - fMax);
3242       const PetscInt *cone, *support;
3243       PetscInt        coneNew[2], supportNew[2];
3244       PetscInt        size, s, r;
3245 
3246       ierr       = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
3247       coneNew[0] = vStartNew + (cone[0] - vStart);
3248       coneNew[1] = vStartNew + (cone[1] - vStart);
3249       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3250 #if defined(PETSC_USE_DEBUG)
3251       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3252       for (p = 0; p < 2; ++p) {
3253         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3254       }
3255 #endif
3256       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
3257       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
3258       for (s = 0; s < size; ++s) {
3259         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3260         for (r = 0; r < 2; ++r) {
3261           if (cone[r+2] == f) break;
3262         }
3263         supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
3264       }
3265       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3266 #if defined(PETSC_USE_DEBUG)
3267       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3268       for (p = 0; p < size; ++p) {
3269         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3270       }
3271 #endif
3272     }
3273     /* Cell hybrid faces have 2 vertices and 2 cells */
3274     for (c = cMax; c < cEnd; ++c) {
3275       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
3276       const PetscInt *cone;
3277       PetscInt        coneNew[2], supportNew[2];
3278 
3279       ierr       = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
3280       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
3281       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
3282       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3283 #if defined(PETSC_USE_DEBUG)
3284       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3285       for (p = 0; p < 2; ++p) {
3286         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3287       }
3288 #endif
3289       supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
3290       supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
3291       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3292 #if defined(PETSC_USE_DEBUG)
3293       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3294       for (p = 0; p < 2; ++p) {
3295         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3296       }
3297 #endif
3298     }
3299     /* Old vertices have identical supports */
3300     for (v = vStart; v < vEnd; ++v) {
3301       const PetscInt  newp = vStartNew + (v - vStart);
3302       const PetscInt *support, *cone;
3303       PetscInt        size, s;
3304 
3305       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
3306       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
3307       for (s = 0; s < size; ++s) {
3308         if (support[s] >= fMax) {
3309           supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (support[s] - fMax);
3310         } else {
3311           PetscInt r = 0;
3312 
3313           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3314           if (cone[1] == v) r = 1;
3315           supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
3316         }
3317       }
3318       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3319 #if defined(PETSC_USE_DEBUG)
3320       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
3321       for (p = 0; p < size; ++p) {
3322         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
3323       }
3324 #endif
3325     }
3326     /* Face vertices have 2 + cells supports */
3327     for (f = fStart; f < fMax; ++f) {
3328       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
3329       const PetscInt *cone, *support;
3330       PetscInt        size, s;
3331 
3332       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
3333       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
3334       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
3335       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
3336       for (s = 0; s < size; ++s) {
3337         PetscInt r = 0;
3338 
3339         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3340         if (support[s] >= cMax) {
3341           supportRef[2+s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (support[s] - cMax);
3342         } else {
3343           if      (cone[1] == f) r = 1;
3344           else if (cone[2] == f) r = 2;
3345           else if (cone[3] == f) r = 3;
3346           supportRef[2+s] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*4 + r;
3347         }
3348       }
3349       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3350 #if defined(PETSC_USE_DEBUG)
3351       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
3352       for (p = 0; p < 2+size; ++p) {
3353         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
3354       }
3355 #endif
3356     }
3357     /* Cell vertices have 4 supports */
3358     for (c = cStart; c < cMax; ++c) {
3359       const PetscInt newp = vStartNew + (vEnd - vStart) + (fMax - fStart) + (c - cStart);
3360       PetscInt       supportNew[4];
3361 
3362       for (r = 0; r < 4; ++r) {
3363         supportNew[r] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
3364       }
3365       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3366     }
3367     ierr = PetscFree(supportRef);CHKERRQ(ierr);
3368     break;
3369   case REFINER_SIMPLEX_3D:
3370     /* All cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
3371     ierr = DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);CHKERRQ(ierr);
3372     for (c = cStart; c < cEnd; ++c) {
3373       const PetscInt  newp = cStartNew + (c - cStart)*8;
3374       const PetscInt *cone, *ornt;
3375       PetscInt        coneNew[4], orntNew[4];
3376 
3377       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
3378       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
3379       /* A tetrahedron: {0, a, c, d} */
3380       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
3381       orntNew[0] = ornt[0];
3382       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
3383       orntNew[1] = ornt[1];
3384       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
3385       orntNew[2] = ornt[2];
3386       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
3387       orntNew[3] = 0;
3388       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
3389       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
3390 #if defined(PETSC_USE_DEBUG)
3391       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
3392       for (p = 0; p < 4; ++p) {
3393         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3394       }
3395 #endif
3396       /* B tetrahedron: {a, 1, b, e} */
3397       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
3398       orntNew[0] = ornt[0];
3399       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
3400       orntNew[1] = ornt[1];
3401       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
3402       orntNew[2] = 0;
3403       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
3404       orntNew[3] = ornt[3];
3405       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
3406       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
3407 #if defined(PETSC_USE_DEBUG)
3408       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
3409       for (p = 0; p < 4; ++p) {
3410         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3411       }
3412 #endif
3413       /* C tetrahedron: {c, b, 2, f} */
3414       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
3415       orntNew[0] = ornt[0];
3416       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
3417       orntNew[1] = 0;
3418       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
3419       orntNew[2] = ornt[2];
3420       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
3421       orntNew[3] = ornt[3];
3422       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
3423       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
3424 #if defined(PETSC_USE_DEBUG)
3425       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
3426       for (p = 0; p < 4; ++p) {
3427         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3428       }
3429 #endif
3430       /* D tetrahedron: {d, e, f, 3} */
3431       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
3432       orntNew[0] = 0;
3433       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
3434       orntNew[1] = ornt[1];
3435       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
3436       orntNew[2] = ornt[2];
3437       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
3438       orntNew[3] = ornt[3];
3439       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
3440       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
3441 #if defined(PETSC_USE_DEBUG)
3442       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
3443       for (p = 0; p < 4; ++p) {
3444         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3445       }
3446 #endif
3447       /* A' tetrahedron: {c, d, a, f} */
3448       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
3449       orntNew[0] = -3;
3450       coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
3451       orntNew[1] = ornt[2] < 0 ? -(GetTriMidEdge_Static(ornt[2], 0)+1) : GetTriMidEdge_Static(ornt[2], 0);
3452       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
3453       orntNew[2] = 0;
3454       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
3455       orntNew[3] = 2;
3456       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
3457       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
3458 #if defined(PETSC_USE_DEBUG)
3459       if ((newp+4 < cStartNew) || (newp+4 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+4, cStartNew, cEndNew);
3460       for (p = 0; p < 4; ++p) {
3461         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3462       }
3463 #endif
3464       /* B' tetrahedron: {e, b, a, f} */
3465       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
3466       orntNew[0] = -2;
3467       coneNew[1] = fStartNew + (cone[3] - fStart)*4 + 3;
3468       orntNew[1] = ornt[3] < 0 ? -(GetTriMidEdge_Static(ornt[3], 1)+1) : GetTriMidEdge_Static(ornt[3], 1);
3469       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
3470       orntNew[2] = 0;
3471       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
3472       orntNew[3] = 0;
3473       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
3474       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
3475 #if defined(PETSC_USE_DEBUG)
3476       if ((newp+5 < cStartNew) || (newp+5 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+5, cStartNew, cEndNew);
3477       for (p = 0; p < 4; ++p) {
3478         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3479       }
3480 #endif
3481       /* C' tetrahedron: {f, a, c, b} */
3482       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
3483       orntNew[0] = -2;
3484       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
3485       orntNew[1] = -2;
3486       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
3487       orntNew[2] = -1;
3488       coneNew[3] = fStartNew + (cone[0] - fStart)*4 + 3;
3489       orntNew[3] = ornt[0] < 0 ? -(GetTriMidEdge_Static(ornt[0], 2)+1) : GetTriMidEdge_Static(ornt[0], 2);
3490       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
3491       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
3492 #if defined(PETSC_USE_DEBUG)
3493       if ((newp+6 < cStartNew) || (newp+6 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+6, cStartNew, cEndNew);
3494       for (p = 0; p < 4; ++p) {
3495         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3496       }
3497 #endif
3498       /* D' tetrahedron: {f, a, e, d} */
3499       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
3500       orntNew[0] = -2;
3501       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
3502       orntNew[1] = -1;
3503       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
3504       orntNew[2] = -2;
3505       coneNew[3] = fStartNew + (cone[1] - fStart)*4 + 3;
3506       orntNew[3] = ornt[1] < 0 ? -(GetTriMidEdge_Static(ornt[1], 1)+1) : GetTriMidEdge_Static(ornt[1], 1);
3507       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
3508       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
3509 #if defined(PETSC_USE_DEBUG)
3510       if ((newp+7 < cStartNew) || (newp+7 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+7, cStartNew, cEndNew);
3511       for (p = 0; p < 4; ++p) {
3512         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3513       }
3514 #endif
3515     }
3516     /* Split faces have 3 edges and the same cells as the parent */
3517     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
3518     ierr = PetscMalloc1(2 + maxSupportSize*3, &supportRef);CHKERRQ(ierr);
3519     for (f = fStart; f < fEnd; ++f) {
3520       const PetscInt  newp = fStartNew + (f - fStart)*4;
3521       const PetscInt *cone, *ornt, *support;
3522       PetscInt        coneNew[3], orntNew[3], coneSize, supportSize, s;
3523 
3524       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
3525       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
3526       /* A triangle */
3527       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
3528       orntNew[0] = ornt[0];
3529       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
3530       orntNew[1] = -2;
3531       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
3532       orntNew[2] = ornt[2];
3533       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
3534       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
3535 #if defined(PETSC_USE_DEBUG)
3536       if ((newp+0 < fStartNew) || (newp+0 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+0, fStartNew, fEndNew);
3537       for (p = 0; p < 3; ++p) {
3538         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3539       }
3540 #endif
3541       /* B triangle */
3542       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
3543       orntNew[0] = ornt[0];
3544       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
3545       orntNew[1] = ornt[1];
3546       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
3547       orntNew[2] = -2;
3548       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
3549       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
3550 #if defined(PETSC_USE_DEBUG)
3551       if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+1, fStartNew, fEndNew);
3552       for (p = 0; p < 3; ++p) {
3553         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3554       }
3555 #endif
3556       /* C triangle */
3557       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
3558       orntNew[0] = -2;
3559       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
3560       orntNew[1] = ornt[1];
3561       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
3562       orntNew[2] = ornt[2];
3563       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
3564       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
3565 #if defined(PETSC_USE_DEBUG)
3566       if ((newp+2 < fStartNew) || (newp+2 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+2, fStartNew, fEndNew);
3567       for (p = 0; p < 3; ++p) {
3568         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3569       }
3570 #endif
3571       /* D triangle */
3572       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
3573       orntNew[0] = 0;
3574       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
3575       orntNew[1] = 0;
3576       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
3577       orntNew[2] = 0;
3578       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
3579       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
3580 #if defined(PETSC_USE_DEBUG)
3581       if ((newp+3 < fStartNew) || (newp+3 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+3, fStartNew, fEndNew);
3582       for (p = 0; p < 3; ++p) {
3583         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3584       }
3585 #endif
3586       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
3587       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
3588       for (r = 0; r < 4; ++r) {
3589         for (s = 0; s < supportSize; ++s) {
3590           PetscInt subf;
3591           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
3592           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3593           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
3594           for (c = 0; c < coneSize; ++c) {
3595             if (cone[c] == f) break;
3596           }
3597           subf = GetTriSubfaceInverse_Static(ornt[c], r);
3598           supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
3599         }
3600         ierr = DMPlexSetSupport(rdm, newp+r, supportRef);CHKERRQ(ierr);
3601 #if defined(PETSC_USE_DEBUG)
3602         if ((newp+r < fStartNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+r, fStartNew, fEndNew);
3603         for (p = 0; p < supportSize; ++p) {
3604           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
3605         }
3606 #endif
3607       }
3608     }
3609     /* Interior faces have 3 edges and 2 cells */
3610     for (c = cStart; c < cEnd; ++c) {
3611       PetscInt        newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8;
3612       const PetscInt *cone, *ornt;
3613       PetscInt        coneNew[3], orntNew[3];
3614       PetscInt        supportNew[2];
3615 
3616       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
3617       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
3618       /* Face A: {c, a, d} */
3619       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
3620       orntNew[0] = ornt[0] < 0 ? -2 : 0;
3621       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
3622       orntNew[1] = ornt[1] < 0 ? -2 : 0;
3623       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 2);
3624       orntNew[2] = ornt[2] < 0 ? -2 : 0;
3625       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3626       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3627 #if defined(PETSC_USE_DEBUG)
3628       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3629       for (p = 0; p < 3; ++p) {
3630         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3631       }
3632 #endif
3633       supportNew[0] = (c - cStart)*8 + 0;
3634       supportNew[1] = (c - cStart)*8 + 0+4;
3635       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3636 #if defined(PETSC_USE_DEBUG)
3637       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3638       for (p = 0; p < 2; ++p) {
3639         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3640       }
3641 #endif
3642       ++newp;
3643       /* Face B: {a, b, e} */
3644       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
3645       orntNew[0] = ornt[0] < 0 ? -2 : 0;
3646       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 0);
3647       orntNew[1] = ornt[3] < 0 ? -2 : 0;
3648       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
3649       orntNew[2] = ornt[1] < 0 ? -2 : 0;
3650       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3651       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3652 #if defined(PETSC_USE_DEBUG)
3653       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3654       for (p = 0; p < 3; ++p) {
3655         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3656       }
3657 #endif
3658       supportNew[0] = (c - cStart)*8 + 1;
3659       supportNew[1] = (c - cStart)*8 + 1+4;
3660       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3661 #if defined(PETSC_USE_DEBUG)
3662       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3663       for (p = 0; p < 2; ++p) {
3664         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3665       }
3666 #endif
3667       ++newp;
3668       /* Face C: {c, f, b} */
3669       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
3670       orntNew[0] = ornt[2] < 0 ? -2 : 0;
3671       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
3672       orntNew[1] = ornt[3] < 0 ? -2 : 0;
3673       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 1);
3674       orntNew[2] = ornt[0] < 0 ? -2 : 0;
3675       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3676       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3677 #if defined(PETSC_USE_DEBUG)
3678       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3679       for (p = 0; p < 3; ++p) {
3680         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3681       }
3682 #endif
3683       supportNew[0] = (c - cStart)*8 + 2;
3684       supportNew[1] = (c - cStart)*8 + 2+4;
3685       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3686 #if defined(PETSC_USE_DEBUG)
3687       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3688       for (p = 0; p < 2; ++p) {
3689         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3690       }
3691 #endif
3692       ++newp;
3693       /* Face D: {d, e, f} */
3694       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 0);
3695       orntNew[0] = ornt[1] < 0 ? -2 : 0;
3696       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
3697       orntNew[1] = ornt[3] < 0 ? -2 : 0;
3698       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
3699       orntNew[2] = ornt[2] < 0 ? -2 : 0;
3700       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3701       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3702 #if defined(PETSC_USE_DEBUG)
3703       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3704       for (p = 0; p < 3; ++p) {
3705         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3706       }
3707 #endif
3708       supportNew[0] = (c - cStart)*8 + 3;
3709       supportNew[1] = (c - cStart)*8 + 3+4;
3710       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3711 #if defined(PETSC_USE_DEBUG)
3712       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3713       for (p = 0; p < 2; ++p) {
3714         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3715       }
3716 #endif
3717       ++newp;
3718       /* Face E: {d, f, a} */
3719       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
3720       orntNew[0] = ornt[2] < 0 ? 0 : -2;
3721       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3722       orntNew[1] = -2;
3723       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
3724       orntNew[2] = ornt[1] < 0 ? -2 : 0;
3725       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3726       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3727 #if defined(PETSC_USE_DEBUG)
3728       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3729       for (p = 0; p < 3; ++p) {
3730         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3731       }
3732 #endif
3733       supportNew[0] = (c - cStart)*8 + 0+4;
3734       supportNew[1] = (c - cStart)*8 + 3+4;
3735       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3736 #if defined(PETSC_USE_DEBUG)
3737       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3738       for (p = 0; p < 2; ++p) {
3739         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3740       }
3741 #endif
3742       ++newp;
3743       /* Face F: {c, a, f} */
3744       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
3745       orntNew[0] = ornt[0] < 0 ? -2 : 0;
3746       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3747       orntNew[1] = 0;
3748       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
3749       orntNew[2] = ornt[2] < 0 ? 0 : -2;
3750       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3751       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3752 #if defined(PETSC_USE_DEBUG)
3753       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3754       for (p = 0; p < 3; ++p) {
3755         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3756       }
3757 #endif
3758       supportNew[0] = (c - cStart)*8 + 0+4;
3759       supportNew[1] = (c - cStart)*8 + 2+4;
3760       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3761 #if defined(PETSC_USE_DEBUG)
3762       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3763       for (p = 0; p < 2; ++p) {
3764         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3765       }
3766 #endif
3767       ++newp;
3768       /* Face G: {e, a, f} */
3769       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
3770       orntNew[0] = ornt[1] < 0 ? -2 : 0;
3771       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3772       orntNew[1] = 0;
3773       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
3774       orntNew[2] = ornt[3] < 0 ? 0 : -2;
3775       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3776       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3777 #if defined(PETSC_USE_DEBUG)
3778       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3779       for (p = 0; p < 3; ++p) {
3780         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3781       }
3782 #endif
3783       supportNew[0] = (c - cStart)*8 + 1+4;
3784       supportNew[1] = (c - cStart)*8 + 3+4;
3785       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3786 #if defined(PETSC_USE_DEBUG)
3787       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3788       for (p = 0; p < 2; ++p) {
3789         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3790       }
3791 #endif
3792       ++newp;
3793       /* Face H: {a, b, f} */
3794       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
3795       orntNew[0] = ornt[0] < 0 ? -2 : 0;
3796       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
3797       orntNew[1] = ornt[3] < 0 ? 0 : -2;
3798       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3799       orntNew[2] = -2;
3800       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3801       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3802 #if defined(PETSC_USE_DEBUG)
3803       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3804       for (p = 0; p < 3; ++p) {
3805         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3806       }
3807 #endif
3808       supportNew[0] = (c - cStart)*8 + 1+4;
3809       supportNew[1] = (c - cStart)*8 + 2+4;
3810       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3811 #if defined(PETSC_USE_DEBUG)
3812       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3813       for (p = 0; p < 2; ++p) {
3814         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3815       }
3816 #endif
3817       ++newp;
3818     }
3819     /* Split Edges have 2 vertices and the same faces as the parent */
3820     for (e = eStart; e < eEnd; ++e) {
3821       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
3822 
3823       for (r = 0; r < 2; ++r) {
3824         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
3825         const PetscInt *cone, *ornt, *support;
3826         PetscInt        coneNew[2], coneSize, c, supportSize, s;
3827 
3828         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
3829         coneNew[0]       = vStartNew + (cone[0] - vStart);
3830         coneNew[1]       = vStartNew + (cone[1] - vStart);
3831         coneNew[(r+1)%2] = newv;
3832         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3833 #if defined(PETSC_USE_DEBUG)
3834         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
3835         for (p = 0; p < 2; ++p) {
3836           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3837         }
3838 #endif
3839         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
3840         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
3841         for (s = 0; s < supportSize; ++s) {
3842           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
3843           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3844           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
3845           for (c = 0; c < coneSize; ++c) {
3846             if (cone[c] == e) break;
3847           }
3848           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
3849         }
3850         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3851 #if defined(PETSC_USE_DEBUG)
3852         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
3853         for (p = 0; p < supportSize; ++p) {
3854           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
3855         }
3856 #endif
3857       }
3858     }
3859     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
3860     for (f = fStart; f < fEnd; ++f) {
3861       const PetscInt *cone, *ornt, *support;
3862       PetscInt        coneSize, supportSize, s;
3863 
3864       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
3865       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
3866       for (r = 0; r < 3; ++r) {
3867         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
3868         PetscInt        coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
3869         PetscInt        fint[24] = { 1,  7, -1, -1,  0,  5,
3870                                     -1, -1,  1,  6,  0,  4,
3871                                      2,  5,  3,  4, -1, -1,
3872                                     -1, -1,  3,  6,  2,  7};
3873 
3874         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
3875         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
3876         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
3877         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3878 #if defined(PETSC_USE_DEBUG)
3879         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
3880         for (p = 0; p < 2; ++p) {
3881           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3882         }
3883 #endif
3884         supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
3885         supportRef[1] = fStartNew + (f - fStart)*4 + 3;
3886         for (s = 0; s < supportSize; ++s) {
3887           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
3888           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3889           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
3890           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
3891           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
3892           er = GetTriMidEdgeInverse_Static(ornt[c], r);
3893           if (er == eint[c]) {
3894             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
3895           } else {
3896             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
3897             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
3898           }
3899         }
3900         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3901 #if defined(PETSC_USE_DEBUG)
3902         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
3903         for (p = 0; p < intFaces; ++p) {
3904           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
3905         }
3906 #endif
3907       }
3908     }
3909     /* Interior edges have 2 vertices and 4 faces */
3910     for (c = cStart; c < cEnd; ++c) {
3911       const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3912       const PetscInt *cone, *ornt, *fcone;
3913       PetscInt        coneNew[2], supportNew[4], find;
3914 
3915       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
3916       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
3917       ierr = DMPlexGetCone(dm, cone[0], &fcone);CHKERRQ(ierr);
3918       find = GetTriEdge_Static(ornt[0], 0);
3919       coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
3920       ierr = DMPlexGetCone(dm, cone[2], &fcone);CHKERRQ(ierr);
3921       find = GetTriEdge_Static(ornt[2], 1);
3922       coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
3923       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3924 #if defined(PETSC_USE_DEBUG)
3925       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
3926       for (p = 0; p < 2; ++p) {
3927         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3928       }
3929 #endif
3930       supportNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
3931       supportNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
3932       supportNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
3933       supportNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
3934       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3935 #if defined(PETSC_USE_DEBUG)
3936       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
3937       for (p = 0; p < 4; ++p) {
3938         if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fEndNew);
3939       }
3940 #endif
3941     }
3942     /* Old vertices have identical supports */
3943     for (v = vStart; v < vEnd; ++v) {
3944       const PetscInt  newp = vStartNew + (v - vStart);
3945       const PetscInt *support, *cone;
3946       PetscInt        size, s;
3947 
3948       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
3949       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
3950       for (s = 0; s < size; ++s) {
3951         PetscInt r = 0;
3952 
3953         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3954         if (cone[1] == v) r = 1;
3955         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
3956       }
3957       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3958 #if defined(PETSC_USE_DEBUG)
3959       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
3960       for (p = 0; p < size; ++p) {
3961         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
3962       }
3963 #endif
3964     }
3965     /* Edge vertices have 2 + face*2 + 0/1 supports */
3966     for (e = eStart; e < eEnd; ++e) {
3967       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
3968       const PetscInt *cone, *support;
3969       PetscInt       *star = NULL, starSize, cellSize = 0, coneSize, size, s;
3970 
3971       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
3972       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
3973       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
3974       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
3975       for (s = 0; s < size; ++s) {
3976         PetscInt r = 0;
3977 
3978         ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
3979         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3980         for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
3981         supportRef[2+s*2+0] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
3982         supportRef[2+s*2+1] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
3983       }
3984       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
3985       for (s = 0; s < starSize*2; s += 2) {
3986         const PetscInt *cone, *ornt;
3987         PetscInt        e01, e23;
3988 
3989         if ((star[s] >= cStart) && (star[s] < cEnd)) {
3990           /* Check edge 0-1 */
3991           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
3992           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
3993           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
3994           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
3995           /* Check edge 2-3 */
3996           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
3997           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
3998           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
3999           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
4000           if ((e01 == e) || (e23 == e)) {supportRef[2+size*2+cellSize++] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (star[s] - cStart);}
4001         }
4002       }
4003       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
4004       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4005 #if defined(PETSC_USE_DEBUG)
4006       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
4007       for (p = 0; p < 2+size*2+cellSize; ++p) {
4008         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
4009       }
4010 #endif
4011     }
4012     ierr = PetscFree(supportRef);CHKERRQ(ierr);
4013     ierr = DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);CHKERRQ(ierr);
4014     break;
4015   case REFINER_HYBRID_SIMPLEX_3D:
4016     ierr = DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);CHKERRQ(ierr);
4017     /* Interior cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
4018     ierr = DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);CHKERRQ(ierr);
4019     for (c = cStart; c < cMax; ++c) {
4020       const PetscInt  newp = cStartNew + (c - cStart)*8;
4021       const PetscInt *cone, *ornt;
4022       PetscInt        coneNew[4], orntNew[4];
4023 
4024       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
4025       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
4026       /* A tetrahedron: {0, a, c, d} */
4027       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
4028       orntNew[0] = ornt[0];
4029       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
4030       orntNew[1] = ornt[1];
4031       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
4032       orntNew[2] = ornt[2];
4033       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 0;
4034       orntNew[3] = 0;
4035       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
4036       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
4037 #if defined(PETSC_USE_DEBUG)
4038       if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cMaxNew);
4039       for (p = 0; p < 4; ++p) {
4040         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4041       }
4042 #endif
4043       /* B tetrahedron: {a, 1, b, e} */
4044       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
4045       orntNew[0] = ornt[0];
4046       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
4047       orntNew[1] = ornt[1];
4048       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 1;
4049       orntNew[2] = 0;
4050       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
4051       orntNew[3] = ornt[3];
4052       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
4053       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
4054 #if defined(PETSC_USE_DEBUG)
4055       if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cMaxNew);
4056       for (p = 0; p < 4; ++p) {
4057         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4058       }
4059 #endif
4060       /* C tetrahedron: {c, b, 2, f} */
4061       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
4062       orntNew[0] = ornt[0];
4063       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 2;
4064       orntNew[1] = 0;
4065       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
4066       orntNew[2] = ornt[2];
4067       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
4068       orntNew[3] = ornt[3];
4069       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
4070       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
4071 #if defined(PETSC_USE_DEBUG)
4072       if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cMaxNew);
4073       for (p = 0; p < 4; ++p) {
4074         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4075       }
4076 #endif
4077       /* D tetrahedron: {d, e, f, 3} */
4078       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 3;
4079       orntNew[0] = 0;
4080       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
4081       orntNew[1] = ornt[1];
4082       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
4083       orntNew[2] = ornt[2];
4084       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
4085       orntNew[3] = ornt[3];
4086       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
4087       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
4088 #if defined(PETSC_USE_DEBUG)
4089       if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cMaxNew);
4090       for (p = 0; p < 4; ++p) {
4091         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4092       }
4093 #endif
4094       /* A' tetrahedron: {d, a, c, f} */
4095       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 0;
4096       orntNew[0] = -3;
4097       coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
4098       orntNew[1] = ornt[2] < 0 ? -(GetTriMidEdge_Static(ornt[2], 0)+1) : GetTriMidEdge_Static(ornt[2], 0);
4099       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 5;
4100       orntNew[2] = 0;
4101       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 4;
4102       orntNew[3] = 2;
4103       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
4104       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
4105 #if defined(PETSC_USE_DEBUG)
4106       if ((newp+4 < cStartNew) || (newp+4 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+4, cStartNew, cMaxNew);
4107       for (p = 0; p < 4; ++p) {
4108         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4109       }
4110 #endif
4111       /* B' tetrahedron: {e, b, a, f} */
4112       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 1;
4113       orntNew[0] = -3;
4114       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 6;
4115       orntNew[1] = 1;
4116       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 7;
4117       orntNew[2] = 0;
4118       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + 3;
4119       orntNew[3] = ornt[3] < 0 ? -(GetTriMidEdge_Static(ornt[3], 0)+1) : GetTriMidEdge_Static(ornt[3], 0);
4120       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
4121       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
4122 #if defined(PETSC_USE_DEBUG)
4123       if ((newp+5 < cStartNew) || (newp+5 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+5, cStartNew, cMaxNew);
4124       for (p = 0; p < 4; ++p) {
4125         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4126       }
4127 #endif
4128       /* C' tetrahedron: {b, f, c, a} */
4129       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 2;
4130       orntNew[0] = -3;
4131       coneNew[1] = fStartNew + (cone[0] - fStart)*4 + 3;
4132       orntNew[1] = ornt[0] < 0 ? -(GetTriMidEdge_Static(ornt[0], 2)+1) : GetTriMidEdge_Static(ornt[0], 2);
4133       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 5;
4134       orntNew[2] = -3;
4135       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 7;
4136       orntNew[3] = -2;
4137       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
4138       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
4139 #if defined(PETSC_USE_DEBUG)
4140       if ((newp+6 < cStartNew) || (newp+6 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+6, cStartNew, cMaxNew);
4141       for (p = 0; p < 4; ++p) {
4142         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4143       }
4144 #endif
4145       /* D' tetrahedron: {f, e, d, a} */
4146       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 3;
4147       orntNew[0] = -3;
4148       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 4;
4149       orntNew[1] = -3;
4150       coneNew[2] = fStartNew + (cone[1] - fStart)*4 + 3;
4151       orntNew[2] = ornt[1] < 0 ? -(GetTriMidEdge_Static(ornt[1], 0)+1) : GetTriMidEdge_Static(ornt[1], 0);
4152       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 6;
4153       orntNew[3] = -3;
4154       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
4155       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
4156 #if defined(PETSC_USE_DEBUG)
4157       if ((newp+7 < cStartNew) || (newp+7 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+7, cStartNew, cMaxNew);
4158       for (p = 0; p < 4; ++p) {
4159         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4160       }
4161 #endif
4162     }
4163     /* Hybrid cells have 5 faces */
4164     for (c = cMax; c < cEnd; ++c) {
4165       const PetscInt  newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4;
4166       const PetscInt *cone, *ornt, *fornt;
4167       PetscInt        coneNew[5], orntNew[5], o, of, i;
4168 
4169       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
4170       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
4171       ierr = DMPlexGetConeOrientation(dm, cone[0], &fornt);CHKERRQ(ierr);
4172       o = ornt[0] < 0 ? -1 : 1;
4173       for (r = 0; r < 3; ++r) {
4174         coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], r);
4175         orntNew[0] = ornt[0];
4176         coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], r);
4177         orntNew[1] = ornt[1];
4178         of = fornt[GetTriEdge_Static(ornt[0], r)]       < 0 ? -1 : 1;
4179         i  = GetTriEdgeInverse_Static(ornt[0], r)       + 2;
4180         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], r)]       - fMax)*2 + (o*of < 0 ? 1 : 0);
4181         orntNew[i] = 0;
4182         i  = GetTriEdgeInverse_Static(ornt[0], (r+1)%3) + 2;
4183         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + GetTriSubface_Static(ornt[0], r);
4184         orntNew[i] = 0;
4185         of = fornt[GetTriEdge_Static(ornt[0], (r+2)%3)] < 0 ? -1 : 1;
4186         i  = GetTriEdgeInverse_Static(ornt[0], (r+2)%3) + 2;
4187         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], (r+2)%3)] - fMax)*2 + (o*of < 0 ? 0 : 1);
4188         orntNew[i] = 0;
4189         ierr = DMPlexSetCone(rdm, newp+r, coneNew);CHKERRQ(ierr);
4190         ierr = DMPlexSetConeOrientation(rdm, newp+r, orntNew);CHKERRQ(ierr);
4191 #if defined(PETSC_USE_DEBUG)
4192         if ((newp+r < cMaxNew) || (newp+r >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", newp+r, cMaxNew, cEndNew);
4193         for (p = 0; p < 2; ++p) {
4194           if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4195         }
4196         for (p = 2; p < 5; ++p) {
4197           if ((coneNew[p] < fMaxNew)   || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", coneNew[p], fMaxNew, fEndNew);
4198         }
4199 #endif
4200       }
4201       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + 3;
4202       orntNew[0] = 0;
4203       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + 3;
4204       orntNew[1] = 0;
4205       coneNew[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;
4206       orntNew[2] = 0;
4207       coneNew[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;
4208       orntNew[3] = 0;
4209       coneNew[4] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;
4210       orntNew[4] = 0;
4211       ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
4212       ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
4213 #if defined(PETSC_USE_DEBUG)
4214       if ((newp+3 < cMaxNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", newp+3, cMaxNew, cEndNew);
4215       for (p = 0; p < 2; ++p) {
4216         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4217       }
4218       for (p = 2; p < 5; ++p) {
4219         if ((coneNew[p] < fMaxNew)   || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", coneNew[p], fMaxNew, fEndNew);
4220       }
4221 #endif
4222     }
4223     /* Split faces have 3 edges and the same cells as the parent */
4224     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
4225     ierr = PetscMalloc1(2 + maxSupportSize*2, &supportRef);CHKERRQ(ierr);
4226     for (f = fStart; f < fMax; ++f) {
4227       const PetscInt  newp = fStartNew + (f - fStart)*4;
4228       const PetscInt *cone, *ornt, *support;
4229       PetscInt        coneNew[3], orntNew[3], coneSize, supportSize, s;
4230 
4231       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
4232       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
4233       /* A triangle */
4234       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
4235       orntNew[0] = ornt[0];
4236       coneNew[1] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
4237       orntNew[1] = -2;
4238       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
4239       orntNew[2] = ornt[2];
4240       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
4241       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
4242 #if defined(PETSC_USE_DEBUG)
4243       if ((newp+0 < fStartNew) || (newp+0 >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+0, fStartNew, fMaxNew);
4244       for (p = 0; p < 3; ++p) {
4245         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4246       }
4247 #endif
4248       /* B triangle */
4249       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
4250       orntNew[0] = ornt[0];
4251       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
4252       orntNew[1] = ornt[1];
4253       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
4254       orntNew[2] = -2;
4255       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
4256       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
4257 #if defined(PETSC_USE_DEBUG)
4258       if ((newp+1 < fStartNew) || (newp+1 >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+1, fStartNew, fMaxNew);
4259       for (p = 0; p < 3; ++p) {
4260         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4261       }
4262 #endif
4263       /* C triangle */
4264       coneNew[0] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
4265       orntNew[0] = -2;
4266       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
4267       orntNew[1] = ornt[1];
4268       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
4269       orntNew[2] = ornt[2];
4270       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
4271       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
4272 #if defined(PETSC_USE_DEBUG)
4273       if ((newp+2 < fStartNew) || (newp+2 >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+2, fStartNew, fMaxNew);
4274       for (p = 0; p < 3; ++p) {
4275         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4276       }
4277 #endif
4278       /* D triangle */
4279       coneNew[0] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
4280       orntNew[0] = 0;
4281       coneNew[1] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
4282       orntNew[1] = 0;
4283       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
4284       orntNew[2] = 0;
4285       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
4286       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
4287 #if defined(PETSC_USE_DEBUG)
4288       if ((newp+3 < fStartNew) || (newp+3 >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+3, fStartNew, fMaxNew);
4289       for (p = 0; p < 3; ++p) {
4290         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4291       }
4292 #endif
4293       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
4294       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
4295       for (r = 0; r < 4; ++r) {
4296         for (s = 0; s < supportSize; ++s) {
4297           PetscInt subf;
4298           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
4299           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
4300           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
4301           for (c = 0; c < coneSize; ++c) {
4302             if (cone[c] == f) break;
4303           }
4304           subf = GetTriSubfaceInverse_Static(ornt[c], r);
4305           if (support[s] < cMax) {
4306             supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
4307           } else {
4308             supportRef[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (r==3 ? r : subf);
4309           }
4310         }
4311         ierr = DMPlexSetSupport(rdm, newp+r, supportRef);CHKERRQ(ierr);
4312 #if defined(PETSC_USE_DEBUG)
4313         if ((newp+r < fStartNew) || (newp+r >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+r, fStartNew, fMaxNew);
4314         for (p = 0; p < supportSize; ++p) {
4315           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior or hybrid cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
4316         }
4317 #endif
4318       }
4319     }
4320     /* Interior cell faces have 3 edges and 2 cells */
4321     for (c = cStart; c < cMax; ++c) {
4322       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8;
4323       const PetscInt *cone, *ornt;
4324       PetscInt        coneNew[3], orntNew[3];
4325       PetscInt        supportNew[2];
4326 
4327       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
4328       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
4329       /* Face A: {c, a, d} */
4330       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
4331       orntNew[0] = ornt[0] < 0 ? -2 : 0;
4332       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
4333       orntNew[1] = ornt[1] < 0 ? -2 : 0;
4334       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 2);
4335       orntNew[2] = ornt[2] < 0 ? -2 : 0;
4336       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4337       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4338 #if defined(PETSC_USE_DEBUG)
4339       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4340       for (p = 0; p < 3; ++p) {
4341         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4342       }
4343 #endif
4344       supportNew[0] = (c - cStart)*8 + 0;
4345       supportNew[1] = (c - cStart)*8 + 0+4;
4346       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4347 #if defined(PETSC_USE_DEBUG)
4348       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4349       for (p = 0; p < 2; ++p) {
4350         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4351       }
4352 #endif
4353       ++newp;
4354       /* Face B: {a, b, e} */
4355       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
4356       orntNew[0] = ornt[0] < 0 ? -2 : 0;
4357       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 0);
4358       orntNew[1] = ornt[3] < 0 ? -2 : 0;
4359       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
4360       orntNew[2] = ornt[1] < 0 ? -2 : 0;
4361       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4362       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4363 #if defined(PETSC_USE_DEBUG)
4364       if ((newp+1 < fStartNew) || (newp+1 >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+1, fStartNew, fMaxNew);
4365       for (p = 0; p < 3; ++p) {
4366         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4367       }
4368 #endif
4369       supportNew[0] = (c - cStart)*8 + 1;
4370       supportNew[1] = (c - cStart)*8 + 1+4;
4371       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4372 #if defined(PETSC_USE_DEBUG)
4373       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4374       for (p = 0; p < 2; ++p) {
4375         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4376       }
4377 #endif
4378       ++newp;
4379       /* Face C: {c, f, b} */
4380       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
4381       orntNew[0] = ornt[2] < 0 ? -2 : 0;
4382       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
4383       orntNew[1] = ornt[3] < 0 ? -2 : 0;
4384       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 1);
4385       orntNew[2] = ornt[0] < 0 ? -2 : 0;
4386       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4387       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4388 #if defined(PETSC_USE_DEBUG)
4389       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4390       for (p = 0; p < 3; ++p) {
4391         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4392       }
4393 #endif
4394       supportNew[0] = (c - cStart)*8 + 2;
4395       supportNew[1] = (c - cStart)*8 + 2+4;
4396       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4397 #if defined(PETSC_USE_DEBUG)
4398       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4399       for (p = 0; p < 2; ++p) {
4400         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4401       }
4402 #endif
4403       ++newp;
4404       /* Face D: {d, e, f} */
4405       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 0);
4406       orntNew[0] = ornt[1] < 0 ? -2 : 0;
4407       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
4408       orntNew[1] = ornt[3] < 0 ? -2 : 0;
4409       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
4410       orntNew[2] = ornt[2] < 0 ? -2 : 0;
4411       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4412       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4413 #if defined(PETSC_USE_DEBUG)
4414       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4415       for (p = 0; p < 3; ++p) {
4416         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4417       }
4418 #endif
4419       supportNew[0] = (c - cStart)*8 + 3;
4420       supportNew[1] = (c - cStart)*8 + 3+4;
4421       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4422 #if defined(PETSC_USE_DEBUG)
4423       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4424       for (p = 0; p < 2; ++p) {
4425         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4426       }
4427 #endif
4428       ++newp;
4429       /* Face E: {d, f, a} */
4430       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
4431       orntNew[0] = ornt[2] < 0 ? 0 : -2;
4432       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
4433       orntNew[1] = -2;
4434       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
4435       orntNew[2] = ornt[1] < 0 ? -2 : 0;
4436       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4437       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4438 #if defined(PETSC_USE_DEBUG)
4439       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4440       for (p = 0; p < 3; ++p) {
4441         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4442       }
4443 #endif
4444       supportNew[0] = (c - cStart)*8 + 0+4;
4445       supportNew[1] = (c - cStart)*8 + 3+4;
4446       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4447 #if defined(PETSC_USE_DEBUG)
4448       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4449       for (p = 0; p < 2; ++p) {
4450         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4451       }
4452 #endif
4453       ++newp;
4454       /* Face F: {c, a, f} */
4455       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
4456       orntNew[0] = ornt[0] < 0 ? -2 : 0;
4457       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
4458       orntNew[1] = 0;
4459       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
4460       orntNew[2] = ornt[2] < 0 ? 0 : -2;
4461       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4462       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4463 #if defined(PETSC_USE_DEBUG)
4464       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4465       for (p = 0; p < 3; ++p) {
4466         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4467       }
4468 #endif
4469       supportNew[0] = (c - cStart)*8 + 0+4;
4470       supportNew[1] = (c - cStart)*8 + 2+4;
4471       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4472 #if defined(PETSC_USE_DEBUG)
4473       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4474       for (p = 0; p < 2; ++p) {
4475         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4476       }
4477 #endif
4478       ++newp;
4479       /* Face G: {e, a, f} */
4480       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
4481       orntNew[0] = ornt[1] < 0 ? -2 : 0;
4482       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
4483       orntNew[1] = 0;
4484       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
4485       orntNew[2] = ornt[3] < 0 ? 0 : -2;
4486       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4487       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4488 #if defined(PETSC_USE_DEBUG)
4489       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4490       for (p = 0; p < 3; ++p) {
4491         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4492       }
4493 #endif
4494       supportNew[0] = (c - cStart)*8 + 1+4;
4495       supportNew[1] = (c - cStart)*8 + 3+4;
4496       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4497 #if defined(PETSC_USE_DEBUG)
4498       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4499       for (p = 0; p < 2; ++p) {
4500         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4501       }
4502 #endif
4503       ++newp;
4504       /* Face H: {a, b, f} */
4505       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
4506       orntNew[0] = ornt[0] < 0 ? -2 : 0;
4507       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
4508       orntNew[1] = ornt[3] < 0 ? 0 : -2;
4509       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
4510       orntNew[2] = -2;
4511       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4512       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4513 #if defined(PETSC_USE_DEBUG)
4514       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4515       for (p = 0; p < 3; ++p) {
4516         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4517       }
4518 #endif
4519       supportNew[0] = (c - cStart)*8 + 1+4;
4520       supportNew[1] = (c - cStart)*8 + 2+4;
4521       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4522 #if defined(PETSC_USE_DEBUG)
4523       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4524       for (p = 0; p < 2; ++p) {
4525         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4526       }
4527 #endif
4528       ++newp;
4529     }
4530     /* Hybrid split faces have 4 edges and same cells */
4531     for (f = fMax; f < fEnd; ++f) {
4532       const PetscInt *cone, *ornt, *support;
4533       PetscInt        coneNew[4], orntNew[4];
4534       PetscInt        supportNew[2], size, s, c;
4535 
4536       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
4537       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
4538       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
4539       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
4540       for (r = 0; r < 2; ++r) {
4541         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;
4542 
4543         coneNew[0]   = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
4544         orntNew[0]   = ornt[0];
4545         coneNew[1]   = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
4546         orntNew[1]   = ornt[1];
4547         coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (cone[2+r] - eMax);
4548         orntNew[2+r] = 0;
4549         coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd      - eMax) + (f - fMax);
4550         orntNew[3-r] = 0;
4551         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4552         ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4553 #if defined(PETSC_USE_DEBUG)
4554         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp, fMaxNew, fEndNew);
4555         for (p = 0; p < 2; ++p) {
4556           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4557         }
4558         for (p = 2; p < 4; ++p) {
4559           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", coneNew[p], eMaxNew, eEndNew);
4560         }
4561 #endif
4562         for (s = 0; s < size; ++s) {
4563           const PetscInt *coneCell, *orntCell, *fornt;
4564           PetscInt        o, of;
4565 
4566           ierr = DMPlexGetCone(dm, support[s], &coneCell);CHKERRQ(ierr);
4567           ierr = DMPlexGetConeOrientation(dm, support[s], &orntCell);CHKERRQ(ierr);
4568           o = orntCell[0] < 0 ? -1 : 1;
4569           for (c = 2; c < 5; ++c) if (coneCell[c] == f) break;
4570           if (c >= 5) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %D in cone of cell %D", f, support[s]);
4571           ierr = DMPlexGetConeOrientation(dm, coneCell[0], &fornt);CHKERRQ(ierr);
4572           of = fornt[c-2] < 0 ? -1 : 1;
4573           supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetTriEdgeInverse_Static(orntCell[0], c-2) + (o*of < 0 ? 1-r : r))%3;
4574         }
4575         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4576 #if defined(PETSC_USE_DEBUG)
4577         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp, fMaxNew, fEndNew);
4578         for (p = 0; p < size; ++p) {
4579           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", supportNew[p], cMaxNew, cEndNew);
4580         }
4581 #endif
4582       }
4583     }
4584     /* Hybrid cell faces have 4 edges and 2 cells */
4585     for (c = cMax; c < cEnd; ++c) {
4586       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3;
4587       const PetscInt *cone, *ornt;
4588       PetscInt        coneNew[4], orntNew[4];
4589       PetscInt        supportNew[2];
4590 
4591       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
4592       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
4593       for (r = 0; r < 3; ++r) {
4594         coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + (r+2)%3;
4595         orntNew[0] = 0;
4596         coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + (r+2)%3;
4597         orntNew[1] = 0;
4598         coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+(r+2)%3] - fMax);
4599         orntNew[2] = 0;
4600         coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+r]       - fMax);
4601         orntNew[3] = 0;
4602         ierr = DMPlexSetCone(rdm, newp+r, coneNew);CHKERRQ(ierr);
4603         ierr = DMPlexSetConeOrientation(rdm, newp+r, orntNew);CHKERRQ(ierr);
4604 #if defined(PETSC_USE_DEBUG)
4605         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp+r, fMaxNew, fEndNew);
4606         for (p = 0; p < 2; ++p) {
4607           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4608         }
4609         for (p = 2; p < 4; ++p) {
4610           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", coneNew[p], eMaxNew, eEndNew);
4611         }
4612 #endif
4613         supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetTriSubface_Static(ornt[0], r);
4614         supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + 3;
4615         ierr          = DMPlexSetSupport(rdm, newp+r, supportNew);CHKERRQ(ierr);
4616 #if defined(PETSC_USE_DEBUG)
4617         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp+r, fMaxNew, fEndNew);
4618         for (p = 0; p < 2; ++p) {
4619           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", supportNew[p], cMaxNew, cEndNew);
4620         }
4621 #endif
4622       }
4623     }
4624     /* Interior split edges have 2 vertices and the same faces as the parent */
4625     for (e = eStart; e < eMax; ++e) {
4626       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
4627 
4628       for (r = 0; r < 2; ++r) {
4629         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
4630         const PetscInt *cone, *ornt, *support;
4631         PetscInt        coneNew[2], coneSize, c, supportSize, s;
4632 
4633         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
4634         coneNew[0]       = vStartNew + (cone[0] - vStart);
4635         coneNew[1]       = vStartNew + (cone[1] - vStart);
4636         coneNew[(r+1)%2] = newv;
4637         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4638 #if defined(PETSC_USE_DEBUG)
4639         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
4640         for (p = 0; p < 2; ++p) {
4641           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
4642         }
4643 #endif
4644         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
4645         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
4646         for (s = 0; s < supportSize; ++s) {
4647           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
4648           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
4649           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
4650           for (c = 0; c < coneSize; ++c) if (cone[c] == e) break;
4651           if (support[s] < fMax) {
4652             supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
4653           } else {
4654             supportRef[s] = fStartNew + (fMax       - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
4655           }
4656         }
4657         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4658 #if defined(PETSC_USE_DEBUG)
4659         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
4660         for (p = 0; p < supportSize; ++p) {
4661           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior or hybrid face [%D, %D)", supportRef[p], fStartNew, fEndNew);
4662         }
4663 #endif
4664       }
4665     }
4666     /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
4667     for (f = fStart; f < fMax; ++f) {
4668       const PetscInt *cone, *ornt, *support;
4669       PetscInt        coneSize, supportSize, s;
4670 
4671       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
4672       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
4673       for (r = 0; r < 3; ++r) {
4674         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
4675         PetscInt        coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
4676         PetscInt        fint[24] = { 1,  7, -1, -1,  0,  5,
4677                                     -1, -1,  1,  6,  0,  4,
4678                                      2,  5,  3,  4, -1, -1,
4679                                     -1, -1,  3,  6,  2,  7};
4680 
4681         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
4682         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
4683         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
4684         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4685 #if defined(PETSC_USE_DEBUG)
4686         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
4687         for (p = 0; p < 2; ++p) {
4688           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
4689         }
4690 #endif
4691         supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
4692         supportRef[1] = fStartNew + (f - fStart)*4 + 3;
4693         for (s = 0; s < supportSize; ++s) {
4694           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
4695           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
4696           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
4697           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
4698           if (support[s] < cMax) {
4699             /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
4700             er = GetTriMidEdgeInverse_Static(ornt[c], r);
4701             if (er == eint[c]) {
4702               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
4703             } else {
4704               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
4705               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
4706             }
4707           } else {
4708             supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (r + 1)%3;
4709           }
4710         }
4711         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4712 #if defined(PETSC_USE_DEBUG)
4713         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
4714         for (p = 0; p < intFaces; ++p) {
4715           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior or hybrid face [%D, %D)", supportRef[p], fStartNew, fEndNew);
4716         }
4717 #endif
4718       }
4719     }
4720     /* Interior cell edges have 2 vertices and 4 faces */
4721     for (c = cStart; c < cMax; ++c) {
4722       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
4723       const PetscInt *cone, *ornt, *fcone;
4724       PetscInt        coneNew[2], supportNew[4], find;
4725 
4726       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
4727       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
4728       ierr = DMPlexGetCone(dm, cone[0], &fcone);CHKERRQ(ierr);
4729       find = GetTriEdge_Static(ornt[0], 0);
4730       coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
4731       ierr = DMPlexGetCone(dm, cone[2], &fcone);CHKERRQ(ierr);
4732       find = GetTriEdge_Static(ornt[2], 1);
4733       coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
4734       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4735 #if defined(PETSC_USE_DEBUG)
4736       if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
4737       for (p = 0; p < 2; ++p) {
4738         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
4739       }
4740 #endif
4741       supportNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
4742       supportNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
4743       supportNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
4744       supportNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
4745       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4746 #if defined(PETSC_USE_DEBUG)
4747       if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
4748       for (p = 0; p < 4; ++p) {
4749         if ((supportNew[p] < fStartNew) || (supportNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fMaxNew);
4750       }
4751 #endif
4752     }
4753     /* Hybrid edges have two vertices and the same faces */
4754     for (e = eMax; e < eEnd; ++e) {
4755       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
4756       const PetscInt *cone, *support, *fcone;
4757       PetscInt        coneNew[2], size, fsize, s;
4758 
4759       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
4760       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
4761       ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
4762       coneNew[0] = vStartNew + (cone[0] - vStart);
4763       coneNew[1] = vStartNew + (cone[1] - vStart);
4764       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4765 #if defined(PETSC_USE_DEBUG)
4766       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
4767       for (p = 0; p < 2; ++p) {
4768         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
4769       }
4770 #endif
4771       for (s = 0; s < size; ++s) {
4772         ierr = DMPlexGetConeSize(dm, support[s], &fsize);CHKERRQ(ierr);
4773         ierr = DMPlexGetCone(dm, support[s], &fcone);CHKERRQ(ierr);
4774         for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
4775         if ((c < 2) || (c > 3)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Edge %D not found in cone of face %D", e, support[s]);
4776         supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + c-2;
4777       }
4778       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4779 #if defined(PETSC_USE_DEBUG)
4780       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
4781       for (p = 0; p < size; ++p) {
4782         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", supportRef[p], fMaxNew, fEndNew);
4783       }
4784 #endif
4785     }
4786     /* Hybrid face edges have 2 vertices and 2+2*cells faces */
4787     for (f = fMax; f < fEnd; ++f) {
4788       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
4789       const PetscInt *cone, *support, *ccone, *cornt;
4790       PetscInt        coneNew[2], size, csize, s;
4791 
4792       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
4793       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
4794       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
4795       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
4796       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
4797       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4798 #if defined(PETSC_USE_DEBUG)
4799       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
4800       for (p = 0; p < 2; ++p) {
4801         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
4802       }
4803 #endif
4804       supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 0;
4805       supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 1;
4806       for (s = 0; s < size; ++s) {
4807         ierr = DMPlexGetConeSize(dm, support[s], &csize);CHKERRQ(ierr);
4808         ierr = DMPlexGetCone(dm, support[s], &ccone);CHKERRQ(ierr);
4809         ierr = DMPlexGetConeOrientation(dm, support[s], &cornt);CHKERRQ(ierr);
4810         for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
4811         if ((c < 2) || (c >= csize)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Hybrid face %D is not in cone of hybrid cell %D", f, support[s]);
4812         supportRef[2+s*2+0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + c-2;
4813         supportRef[2+s*2+1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (c-1)%3;
4814       }
4815       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4816 #if defined(PETSC_USE_DEBUG)
4817       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
4818       for (p = 0; p < 2+size*2; ++p) {
4819         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", supportRef[p], fMaxNew, fEndNew);
4820       }
4821 #endif
4822     }
4823     /* Interior vertices have identical supports */
4824     for (v = vStart; v < vEnd; ++v) {
4825       const PetscInt  newp = vStartNew + (v - vStart);
4826       const PetscInt *support, *cone;
4827       PetscInt        size, s;
4828 
4829       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
4830       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
4831       for (s = 0; s < size; ++s) {
4832         PetscInt r = 0;
4833 
4834         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
4835         if (cone[1] == v) r = 1;
4836         if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
4837         else                   supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (support[s] - eMax);
4838       }
4839       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4840 #if defined(PETSC_USE_DEBUG)
4841       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
4842       for (p = 0; p < size; ++p) {
4843         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior or hybrid edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
4844       }
4845 #endif
4846     }
4847     /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
4848     for (e = eStart; e < eMax; ++e) {
4849       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
4850       const PetscInt *cone, *support;
4851       PetscInt       *star = NULL, starSize, faceSize = 0, cellSize = 0, coneSize, size, s;
4852 
4853       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
4854       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
4855       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
4856       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
4857       for (s = 0; s < size; ++s) {
4858         PetscInt r = 0;
4859 
4860         if (support[s] < fMax) {
4861           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
4862           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
4863           for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
4864           supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
4865           supportRef[2+faceSize+1] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
4866           faceSize += 2;
4867         } else {
4868           supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (fMax       - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (support[s] - fMax);
4869           ++faceSize;
4870         }
4871       }
4872       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
4873       for (s = 0; s < starSize*2; s += 2) {
4874         const PetscInt *cone, *ornt;
4875         PetscInt        e01, e23;
4876 
4877         if ((star[s] >= cStart) && (star[s] < cMax)) {
4878           /* Check edge 0-1 */
4879           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
4880           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
4881           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
4882           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
4883           /* Check edge 2-3 */
4884           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
4885           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
4886           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
4887           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
4888           if ((e01 == e) || (e23 == e)) {supportRef[2+faceSize+cellSize++] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (star[s] - cStart);}
4889         }
4890       }
4891       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
4892       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4893 #if defined(PETSC_USE_DEBUG)
4894       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
4895       for (p = 0; p < 2+faceSize+cellSize; ++p) {
4896         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior or hybrid edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
4897       }
4898 #endif
4899     }
4900     ierr = PetscFree(supportRef);CHKERRQ(ierr);
4901     ierr = DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);CHKERRQ(ierr);
4902     break;
4903   case REFINER_SIMPLEX_TO_HEX_3D:
4904     ierr = DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);CHKERRQ(ierr);
4905     /* All cells have 6 faces */
4906     for (c = cStart; c < cEnd; ++c) {
4907       const PetscInt  newp = cStartNew + (c - cStart)*4;
4908       const PetscInt *cone, *ornt;
4909       PetscInt        coneNew[6];
4910       PetscInt        orntNew[6];
4911 
4912       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
4913       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
4914       /* A hex */
4915       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 0); /* B */
4916       orntNew[0] = ornt[0] < 0 ? -1 : 1;
4917       coneNew[1] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 3;               /* T */
4918       orntNew[1] = -4;
4919       coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 0); /* F */
4920       orntNew[2] = ornt[2] < 0 ? -1 : 1;
4921       coneNew[3] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 0;               /* K */
4922       orntNew[3] = -1;
4923       coneNew[4] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 2;               /* R */
4924       orntNew[4] = 0;
4925       coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 0); /* L */
4926       orntNew[5] = ornt[1] < 0 ? -1 : 1;
4927       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
4928       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
4929 #if defined(PETSC_USE_DEBUG)
4930       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
4931       for (p = 0; p < 6; ++p) {
4932         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
4933       }
4934 #endif
4935       /* B hex */
4936       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 1); /* B */
4937       orntNew[0] = ornt[0] < 0 ? -2 : 0;
4938       coneNew[1] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 4;               /* T */
4939       orntNew[1] = 0;
4940       coneNew[2] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 0;               /* F */
4941       orntNew[2] = 0;
4942       coneNew[3] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 1); /* K */
4943       orntNew[3] = ornt[3] < 0 ? -2 : 0;
4944       coneNew[4] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 1;               /* R */
4945       orntNew[4] = 0;
4946       coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 2); /* L */
4947       orntNew[5] = ornt[1] < 0 ? -4 : 2;
4948       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
4949       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
4950 #if defined(PETSC_USE_DEBUG)
4951       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
4952       for (p = 0; p < 6; ++p) {
4953         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
4954       }
4955 #endif
4956       /* C hex */
4957       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 2); /* B */
4958       orntNew[0] = ornt[0] < 0 ? -4 : 2;
4959       coneNew[1] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 5;               /* T */
4960       orntNew[1] = -4;
4961       coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 1); /* F */
4962       orntNew[2] = ornt[2] < 0 ? -2 : 0;
4963       coneNew[3] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 1;               /* K */
4964       orntNew[3] = -1;
4965       coneNew[4] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 0); /* R */
4966       orntNew[4] = ornt[3] < 0 ? -1 : 1;
4967       coneNew[5] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 2;               /* L */
4968       orntNew[5] = -4;
4969       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
4970       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
4971 #if defined(PETSC_USE_DEBUG)
4972       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
4973       for (p = 0; p < 6; ++p) {
4974         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
4975       }
4976 #endif
4977       /* D hex */
4978       coneNew[0] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 3;               /* B */
4979       orntNew[0] = 0;
4980       coneNew[1] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 2); /* T */
4981       orntNew[1] = ornt[3] < 0 ? -1 : 1;
4982       coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 2); /* F */
4983       orntNew[2] = ornt[2] < 0 ? -4 : 2;
4984       coneNew[3] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 4;               /* K */
4985       orntNew[3] = -1;
4986       coneNew[4] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 5;               /* R */
4987       orntNew[4] = 0;
4988       coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 1); /* L */
4989       orntNew[5] = ornt[1] < 0 ? -2 : 0;
4990       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
4991       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
4992 #if defined(PETSC_USE_DEBUG)
4993       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
4994       for (p = 0; p < 6; ++p) {
4995         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
4996       }
4997 #endif
4998     }
4999     /* Split faces have 4 edges and the same cells as the parent */
5000     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
5001     ierr = PetscMalloc1(2 + maxSupportSize*2, &supportRef);CHKERRQ(ierr);
5002     for (f = fStart; f < fEnd; ++f) {
5003       const PetscInt  newp = fStartNew + (f - fStart)*3;
5004       const PetscInt *cone, *ornt, *support;
5005       PetscInt        coneNew[4], orntNew[4], coneSize, supportSize, s;
5006 
5007       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
5008       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
5009       /* A quad */
5010       coneNew[0] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
5011       orntNew[0] = ornt[2];
5012       coneNew[1] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
5013       orntNew[1] = ornt[0];
5014       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
5015       orntNew[2] = 0;
5016       coneNew[3] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
5017       orntNew[3] = -2;
5018       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
5019       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
5020 #if defined(PETSC_USE_DEBUG)
5021       if ((newp+0 < fStartNew) || (newp+0 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+0, fStartNew, fEndNew);
5022       for (p = 0; p < 4; ++p) {
5023         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5024       }
5025 #endif
5026       /* B quad */
5027       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
5028       orntNew[0] = ornt[0];
5029       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
5030       orntNew[1] = ornt[1];
5031       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
5032       orntNew[2] = 0;
5033       coneNew[3] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
5034       orntNew[3] = -2;
5035       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
5036       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
5037 #if defined(PETSC_USE_DEBUG)
5038       if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+1, fStartNew, fEndNew);
5039       for (p = 0; p < 4; ++p) {
5040         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5041       }
5042 #endif
5043       /* C quad */
5044       coneNew[0] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
5045       orntNew[0] = ornt[1];
5046       coneNew[1] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
5047       orntNew[1] = ornt[2];
5048       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
5049       orntNew[2] = 0;
5050       coneNew[3] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
5051       orntNew[3] = -2;
5052       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
5053       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
5054 #if defined(PETSC_USE_DEBUG)
5055       if ((newp+2 < fStartNew) || (newp+2 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+2, fStartNew, fEndNew);
5056       for (p = 0; p < 4; ++p) {
5057         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5058       }
5059 #endif
5060       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
5061       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
5062       for (r = 0; r < 3; ++r) {
5063         for (s = 0; s < supportSize; ++s) {
5064           PetscInt subf;
5065           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
5066           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
5067           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
5068           for (c = 0; c < coneSize; ++c) {
5069             if (cone[c] == f) break;
5070           }
5071           subf = GetTriSubfaceInverse_Static(ornt[c], r);
5072           supportRef[s] = cStartNew + (support[s] - cStart)*4 + faces[c*3+subf];
5073         }
5074         ierr = DMPlexSetSupport(rdm, newp+r, supportRef);CHKERRQ(ierr);
5075 #if defined(PETSC_USE_DEBUG)
5076         if ((newp+r < fStartNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+r, fStartNew, fEndNew);
5077         for (p = 0; p < supportSize; ++p) {
5078           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
5079         }
5080 #endif
5081       }
5082     }
5083     /* Interior faces have 4 edges and 2 cells */
5084     for (c = cStart; c < cEnd; ++c) {
5085       PetscInt        newp = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6;
5086       const PetscInt *cone, *ornt;
5087       PetscInt        coneNew[4], orntNew[4];
5088       PetscInt        supportNew[2];
5089 
5090       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
5091       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
5092       /* Face {a, g, m, h} */
5093       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],0);
5094       orntNew[0] = 0;
5095       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
5096       orntNew[1] = 0;
5097       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
5098       orntNew[2] = -2;
5099       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],2);
5100       orntNew[3] = -2;
5101       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5102       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
5103 #if defined(PETSC_USE_DEBUG)
5104       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5105       for (p = 0; p < 4; ++p) {
5106         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5107       }
5108 #endif
5109       supportNew[0] = (c - cStart)*4 + 0;
5110       supportNew[1] = (c - cStart)*4 + 1;
5111       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5112 #if defined(PETSC_USE_DEBUG)
5113       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5114       for (p = 0; p < 2; ++p) {
5115         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5116       }
5117 #endif
5118       ++newp;
5119       /* Face {g, b, l , m} */
5120       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],1);
5121       orntNew[0] = -2;
5122       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],0);
5123       orntNew[1] = 0;
5124       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
5125       orntNew[2] = 0;
5126       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
5127       orntNew[3] = -2;
5128       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5129       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
5130 #if defined(PETSC_USE_DEBUG)
5131       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5132       for (p = 0; p < 4; ++p) {
5133         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5134       }
5135 #endif
5136       supportNew[0] = (c - cStart)*4 + 1;
5137       supportNew[1] = (c - cStart)*4 + 2;
5138       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5139 #if defined(PETSC_USE_DEBUG)
5140       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5141       for (p = 0; p < 2; ++p) {
5142         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5143       }
5144 #endif
5145       ++newp;
5146       /* Face {c, g, m, i} */
5147       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],2);
5148       orntNew[0] = 0;
5149       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
5150       orntNew[1] = 0;
5151       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
5152       orntNew[2] = -2;
5153       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],0);
5154       orntNew[3] = -2;
5155       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5156       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
5157 #if defined(PETSC_USE_DEBUG)
5158       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5159       for (p = 0; p < 4; ++p) {
5160         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5161       }
5162 #endif
5163       supportNew[0] = (c - cStart)*4 + 0;
5164       supportNew[1] = (c - cStart)*4 + 2;
5165       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5166 #if defined(PETSC_USE_DEBUG)
5167       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5168       for (p = 0; p < 2; ++p) {
5169         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5170       }
5171 #endif
5172       ++newp;
5173       /* Face {d, h, m, i} */
5174       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],0);
5175       orntNew[0] = 0;
5176       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
5177       orntNew[1] = 0;
5178       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
5179       orntNew[2] = -2;
5180       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],2);
5181       orntNew[3] = -2;
5182       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5183       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
5184 #if defined(PETSC_USE_DEBUG)
5185       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5186       for (p = 0; p < 4; ++p) {
5187         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5188       }
5189 #endif
5190       supportNew[0] = (c - cStart)*4 + 0;
5191       supportNew[1] = (c - cStart)*4 + 3;
5192       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5193 #if defined(PETSC_USE_DEBUG)
5194       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5195       for (p = 0; p < 2; ++p) {
5196         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5197       }
5198 #endif
5199       ++newp;
5200       /* Face {h, m, l, e} */
5201       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
5202       orntNew[0] = 0;
5203       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
5204       orntNew[1] = -2;
5205       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],1);
5206       orntNew[2] = -2;
5207       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],1);
5208       orntNew[3] = 0;
5209       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5210       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
5211 #if defined(PETSC_USE_DEBUG)
5212       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5213       for (p = 0; p < 4; ++p) {
5214         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5215       }
5216 #endif
5217       supportNew[0] = (c - cStart)*4 + 1;
5218       supportNew[1] = (c - cStart)*4 + 3;
5219       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5220 #if defined(PETSC_USE_DEBUG)
5221       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5222       for (p = 0; p < 2; ++p) {
5223         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5224       }
5225 #endif
5226       ++newp;
5227       /* Face {i, m, l, f} */
5228       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
5229       orntNew[0] = 0;
5230       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
5231       orntNew[1] = -2;
5232       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],2);
5233       orntNew[2] = -2;
5234       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],1);
5235       orntNew[3] = 0;
5236       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5237       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
5238 #if defined(PETSC_USE_DEBUG)
5239       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5240       for (p = 0; p < 4; ++p) {
5241         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5242       }
5243 #endif
5244       supportNew[0] = (c - cStart)*4 + 2;
5245       supportNew[1] = (c - cStart)*4 + 3;
5246       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5247 #if defined(PETSC_USE_DEBUG)
5248       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5249       for (p = 0; p < 2; ++p) {
5250         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5251       }
5252 #endif
5253       ++newp;
5254     }
5255     /* Split Edges have 2 vertices and the same faces as the parent */
5256     for (e = eStart; e < eEnd; ++e) {
5257       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
5258 
5259       for (r = 0; r < 2; ++r) {
5260         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
5261         const PetscInt *cone, *ornt, *support;
5262         PetscInt        coneNew[2], coneSize, c, supportSize, s;
5263 
5264         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
5265         coneNew[0]       = vStartNew + (cone[0] - vStart);
5266         coneNew[1]       = vStartNew + (cone[1] - vStart);
5267         coneNew[(r+1)%2] = newv;
5268         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5269 #if defined(PETSC_USE_DEBUG)
5270         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
5271         for (p = 0; p < 2; ++p) {
5272           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
5273         }
5274 #endif
5275         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
5276         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
5277         for (s = 0; s < supportSize; ++s) {
5278           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
5279           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
5280           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
5281           for (c = 0; c < coneSize; ++c) {
5282             if (cone[c] == e) break;
5283           }
5284           supportRef[s] = fStartNew + (support[s] - fStart)*3 + (c + (ornt[c] < 0 ? 1-r : r))%3;
5285         }
5286         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
5287 #if defined(PETSC_USE_DEBUG)
5288         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
5289         for (p = 0; p < supportSize; ++p) {
5290           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
5291         }
5292 #endif
5293       }
5294     }
5295     /* Face edges have 2 vertices and 2 + cell faces supports */
5296     for (f = fStart; f < fEnd; ++f) {
5297       const PetscInt *cone, *ornt, *support;
5298       PetscInt        coneSize, supportSize, s;
5299 
5300       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
5301       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
5302       for (r = 0; r < 3; ++r) {
5303         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
5304         PetscInt        coneNew[2];
5305         PetscInt        fint[4][3] = { {0, 1, 2},
5306                                        {3, 4, 0},
5307                                        {2, 5, 3},
5308                                        {1, 4, 5} };
5309 
5310         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
5311         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
5312         coneNew[1] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + f - fStart;
5313         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5314 #if defined(PETSC_USE_DEBUG)
5315         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
5316         for (p = 0; p < 2; ++p) {
5317           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
5318         }
5319 #endif
5320         supportRef[0] = fStartNew + (f - fStart)*3 + (r+0)%3;
5321         supportRef[1] = fStartNew + (f - fStart)*3 + (r+1)%3;
5322         for (s = 0; s < supportSize; ++s) {
5323           PetscInt er;
5324           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
5325           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
5326           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
5327           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
5328           er = GetTriInteriorEdgeInverse_Static(ornt[c], r);
5329           supportRef[2+s] = fStartNew + (fEnd - fStart)*3 + (support[s] - cStart)*6 + fint[c][er];
5330         }
5331         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
5332 #if defined(PETSC_USE_DEBUG)
5333         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
5334         for (p = 0; p < supportSize + 2; ++p) {
5335           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
5336         }
5337 #endif
5338       }
5339     }
5340     /* Interior cell edges have 2 vertices and 3 faces */
5341     for (c = cStart; c < cEnd; ++c) {
5342       const PetscInt *cone;
5343       PetscInt       fint[4][3] = { {0,1,2},
5344                                     {0,3,4},
5345                                     {2,3,5},
5346                                     {1,4,5} } ;
5347 
5348       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
5349       for (r = 0; r < 4; r++) {
5350         PetscInt       coneNew[2], supportNew[3];
5351         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + r;
5352 
5353         coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
5354         coneNew[1] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd -fStart) + c - cStart;
5355         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5356 #if defined(PETSC_USE_DEBUG)
5357         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
5358         for (p = 0; p < 2; ++p) {
5359           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
5360         }
5361 #endif
5362         supportNew[0] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + fint[r][0];
5363         supportNew[1] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + fint[r][1];
5364         supportNew[2] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + fint[r][2];
5365         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5366 #if defined(PETSC_USE_DEBUG)
5367         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
5368         for (p = 0; p < 3; ++p) {
5369           if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fEndNew);
5370         }
5371 #endif
5372       }
5373     }
5374     /* Old vertices have identical supports */
5375     for (v = vStart; v < vEnd; ++v) {
5376       const PetscInt  newp = vStartNew + (v - vStart);
5377       const PetscInt *support, *cone;
5378       PetscInt        size, s;
5379 
5380       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
5381       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
5382       for (s = 0; s < size; ++s) {
5383         PetscInt r = 0;
5384 
5385         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
5386         if (cone[1] == v) r = 1;
5387         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
5388       }
5389       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
5390 #if defined(PETSC_USE_DEBUG)
5391       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
5392       for (p = 0; p < size; ++p) {
5393         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
5394       }
5395 #endif
5396     }
5397     /* Edge vertices have 2 + faces supports */
5398     for (e = eStart; e < eEnd; ++e) {
5399       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
5400       const PetscInt *cone, *support;
5401       PetscInt        size, s;
5402 
5403       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
5404       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
5405       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
5406       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
5407       for (s = 0; s < size; ++s) {
5408         PetscInt r = 0, coneSize;
5409 
5410         ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
5411         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
5412         for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
5413         supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + r;
5414       }
5415       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
5416 #if defined(PETSC_USE_DEBUG)
5417       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
5418       for (p = 0; p < 2+size; ++p) {
5419         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
5420       }
5421 #endif
5422     }
5423     /* Face vertices have 3 + cells supports */
5424     for (f = fStart; f < fEnd; ++f) {
5425       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
5426       const PetscInt *cone, *support;
5427       PetscInt        size, s;
5428 
5429       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
5430       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
5431       supportRef[0] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
5432       supportRef[1] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
5433       supportRef[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
5434       for (s = 0; s < size; ++s) {
5435         PetscInt r = 0, coneSize;
5436 
5437         ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
5438         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
5439         for (r = 0; r < coneSize; ++r) {if (cone[r] == f) break;}
5440         supportRef[3+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (support[s] - cStart)*4 + r;
5441       }
5442       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
5443 #if defined(PETSC_USE_DEBUG)
5444       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
5445       for (p = 0; p < 3+size; ++p) {
5446         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
5447       }
5448 #endif
5449     }
5450     /* Interior cell vertices have 4 supports */
5451     for (c = cStart; c < cEnd; ++c) {
5452       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + c - cStart;
5453       supportRef[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
5454       supportRef[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
5455       supportRef[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
5456       supportRef[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
5457       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
5458 #if defined(PETSC_USE_DEBUG)
5459       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
5460       for (p = 0; p < 4; ++p) {
5461         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
5462       }
5463 #endif
5464     }
5465     ierr = PetscFree(supportRef);CHKERRQ(ierr);
5466     ierr = DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);CHKERRQ(ierr);
5467     break;
5468   case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
5469     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
5470     cMax = PetscMin(cEnd, cMax);
5471     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
5472     fMax = PetscMin(fEnd, fMax);
5473     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
5474     eMax = PetscMin(eEnd, eMax);
5475     ierr = DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);CHKERRQ(ierr);
5476     /* All cells have 6 faces */
5477     for (c = cStart; c < cMax; ++c) {
5478       const PetscInt  newp = cStartNew + (c - cStart)*4;
5479       const PetscInt *cone, *ornt;
5480       PetscInt        coneNew[6];
5481       PetscInt        orntNew[6];
5482 
5483       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
5484 #if defined(PETSC_USE_DEBUG)
5485       for (p = 0; p < 4; ++p) {
5486         if (cone[p] >= fMax) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position %D for cell %D", cone[p], p, fMax, c);
5487       }
5488 #endif
5489       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
5490       /* A hex */
5491       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 0); /* B */
5492       orntNew[0] = ornt[0] < 0 ? -1 : 1;
5493       coneNew[1] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 3;               /* T */
5494       orntNew[1] = -4;
5495       coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 0); /* F */
5496       orntNew[2] = ornt[2] < 0 ? -1 : 1;
5497       coneNew[3] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 0;               /* K */
5498       orntNew[3] = -1;
5499       coneNew[4] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 2;               /* R */
5500       orntNew[4] = 0;
5501       coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 0); /* L */
5502       orntNew[5] = ornt[1] < 0 ? -1 : 1;
5503       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
5504       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
5505 #if defined(PETSC_USE_DEBUG)
5506       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
5507       for (p = 0; p < 6; ++p) {
5508         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5509       }
5510 #endif
5511       /* B hex */
5512       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 1); /* B */
5513       orntNew[0] = ornt[0] < 0 ? -2 : 0;
5514       coneNew[1] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 4;               /* T */
5515       orntNew[1] = 0;
5516       coneNew[2] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 0;               /* F */
5517       orntNew[2] = 0;
5518       coneNew[3] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 1); /* K */
5519       orntNew[3] = ornt[3] < 0 ? -2 : 0;
5520       coneNew[4] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 1;               /* R */
5521       orntNew[4] = 0;
5522       coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 2); /* L */
5523       orntNew[5] = ornt[1] < 0 ? -4 : 2;
5524       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
5525       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
5526 #if defined(PETSC_USE_DEBUG)
5527       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
5528       for (p = 0; p < 6; ++p) {
5529         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5530       }
5531 #endif
5532       /* C hex */
5533       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 2); /* B */
5534       orntNew[0] = ornt[0] < 0 ? -4 : 2;
5535       coneNew[1] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 5;               /* T */
5536       orntNew[1] = -4;
5537       coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 1); /* F */
5538       orntNew[2] = ornt[2] < 0 ? -2 : 0;
5539       coneNew[3] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 1;               /* K */
5540       orntNew[3] = -1;
5541       coneNew[4] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 0); /* R */
5542       orntNew[4] = ornt[3] < 0 ? -1 : 1;
5543       coneNew[5] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 2;               /* L */
5544       orntNew[5] = -4;
5545       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
5546       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
5547 #if defined(PETSC_USE_DEBUG)
5548       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
5549       for (p = 0; p < 6; ++p) {
5550         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5551       }
5552 #endif
5553       /* D hex */
5554       coneNew[0] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 3;               /* B */
5555       orntNew[0] = 0;
5556       coneNew[1] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 2); /* T */
5557       orntNew[1] = ornt[3] < 0 ? -1 : 1;
5558       coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 2); /* F */
5559       orntNew[2] = ornt[2] < 0 ? -4 : 2;
5560       coneNew[3] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 4;               /* K */
5561       orntNew[3] = -1;
5562       coneNew[4] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 5;               /* R */
5563       orntNew[4] = 0;
5564       coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 1); /* L */
5565       orntNew[5] = ornt[1] < 0 ? -2 : 0;
5566       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
5567       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
5568 #if defined(PETSC_USE_DEBUG)
5569       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
5570       for (p = 0; p < 6; ++p) {
5571         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5572       }
5573 #endif
5574     }
5575     for (c = cMax; c < cEnd; ++c) {
5576       const PetscInt  newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*3;
5577       const PetscInt *cone, *ornt, *fornt;
5578       PetscInt        coneNew[6], orntNew[6];
5579       PetscInt        o, of, cf;
5580 
5581       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
5582 #if defined(PETSC_USE_DEBUG)
5583       if (cone[0] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position 0 for cell %D", cone[0], fMax, c);
5584       if (cone[1] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position 1 for cell %D", cone[1], fMax, c);
5585       if (cone[2] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected face %D (fMax %D) in cone position 2 for cell %D", cone[2], fMax, c);
5586       if (cone[3] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected face %D (fMax %D) in cone position 3 for cell %D", cone[3], fMax, c);
5587       if (cone[4] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected face %D (fMax %D) in cone position 4 for cell %D", cone[4], fMax, c);
5588 #endif
5589       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
5590       ierr = DMPlexGetConeOrientation(dm, cone[0], &fornt);CHKERRQ(ierr);
5591       o    = ornt[0] < 0 ? -1 : 1;
5592       /* A hex */
5593       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 0);                            /* B */
5594       orntNew[0] = ornt[0] < 0 ? -1 :  1;
5595       coneNew[1] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 0);                            /* T */
5596       orntNew[1] = ornt[1] < 0 ?  1 : -1;
5597       cf         = GetTriEdge_Static(ornt[0], 2);
5598       of         = fornt[cf] < 0 ? -1 : 1;
5599       coneNew[2] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (cone[2+cf] - fMax)*2 + (o*of < 0 ? 0 : 1); /* F */
5600       orntNew[2] = o*of < 0 ? 0 : -1;
5601       coneNew[3] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;         /* K */
5602       orntNew[3] = -1;
5603       coneNew[4] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;         /* R */
5604       orntNew[4] = 0;
5605       cf         = GetTriEdge_Static(ornt[0], 0);
5606       of         = fornt[cf] < 0 ? -1 : 1;
5607       coneNew[5] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (cone[2+cf] - fMax)*2 + (o*of < 0 ? 1 : 0); /* L */
5608       orntNew[5] = o*of < 0 ? 1 : -4;
5609       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
5610       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
5611 #if defined(PETSC_USE_DEBUG)
5612       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
5613       for (p = 0; p < 6; ++p) {
5614         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5615       }
5616 #endif
5617       /* B hex */
5618       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 1);                            /* B */
5619       orntNew[0] = ornt[0] < 0 ? -2 :  0;
5620       coneNew[1] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 1);                            /* T */
5621       orntNew[1] = ornt[1] < 0 ?  2 : -4;
5622       coneNew[2] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;         /* F */
5623       orntNew[2] = 0;
5624       cf         = GetTriEdge_Static(ornt[0], 1);
5625       of         = fornt[cf] < 0 ? -1 : 1;
5626       coneNew[3] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (cone[2+cf] - fMax)*2 + (o*of < 0 ? 1 : 0); /* K */
5627       orntNew[3] = o*of < 0 ? 0 : -1;
5628       coneNew[4] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;         /* R */
5629       orntNew[4] = -1;
5630       cf         = GetTriEdge_Static(ornt[0], 0);
5631       of         = fornt[cf] < 0 ? -1 : 1;
5632       coneNew[5] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (cone[2+cf] - fMax)*2 + (o*of < 0 ? 0 : 1); /* L */
5633       orntNew[5] = o*of < 0 ? 1 : -4;
5634       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
5635       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
5636 #if defined(PETSC_USE_DEBUG)
5637       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
5638       for (p = 0; p < 6; ++p) {
5639         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5640       }
5641 #endif
5642       /* C hex */
5643       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 2);                            /* B */
5644       orntNew[0] = ornt[0] < 0 ? -4 : 2;
5645       coneNew[1] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 2);                            /* T */
5646       orntNew[1] = ornt[1] < 0 ? 0 : -2;
5647       cf         = GetTriEdge_Static(ornt[0], 2);
5648       of         = fornt[cf] < 0 ? -1 : 1;
5649       coneNew[2] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (cone[2+cf] - fMax)*2 + (o*of < 0 ? 1 : 0); /* F */
5650       orntNew[2] = o*of < 0 ? 0 : -1;
5651       coneNew[3] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;         /* K */
5652       orntNew[3] = 0;
5653       cf         = GetTriEdge_Static(ornt[0], 1);
5654       of         = fornt[cf] < 0 ? -1 : 1;
5655       coneNew[4] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (cone[2+cf] - fMax)*2 + (o*of < 0 ? 0 : 1); /* R */
5656       orntNew[4] = o*of < 0 ? 0 : -1;
5657       coneNew[5] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;         /* L */
5658       orntNew[5] = -4;
5659       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
5660       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
5661 #if defined(PETSC_USE_DEBUG)
5662       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
5663       for (p = 0; p < 6; ++p) {
5664         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5665       }
5666 #endif
5667     }
5668 
5669     /* Split faces have 4 edges and the same cells as the parent */
5670     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
5671     ierr = PetscMalloc1(2 + maxSupportSize*2, &supportRef);CHKERRQ(ierr);
5672     for (f = fStart; f < fMax; ++f) {
5673       const PetscInt  newp = fStartNew + (f - fStart)*3;
5674       const PetscInt *cone, *ornt, *support;
5675       PetscInt        coneNew[4], orntNew[4], coneSize, supportSize, s;
5676 
5677       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
5678 #if defined(PETSC_USE_DEBUG)
5679       for (p = 0; p < 3; ++p) {
5680         if (cone[p] >= eMax) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid edge %D (eMax %D) in cone position %D for face %D", cone[p], p, eMax, f);
5681       }
5682 #endif
5683       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
5684       /* A quad */
5685       coneNew[0] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
5686       orntNew[0] = ornt[2];
5687       coneNew[1] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
5688       orntNew[1] = ornt[0];
5689       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
5690       orntNew[2] = 0;
5691       coneNew[3] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
5692       orntNew[3] = -2;
5693       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
5694       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
5695 #if defined(PETSC_USE_DEBUG)
5696       if ((newp+0 < fStartNew) || (newp+0 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+0, fStartNew, fEndNew);
5697       for (p = 0; p < 4; ++p) {
5698         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5699       }
5700 #endif
5701       /* B quad */
5702       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
5703       orntNew[0] = ornt[0];
5704       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
5705       orntNew[1] = ornt[1];
5706       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
5707       orntNew[2] = 0;
5708       coneNew[3] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
5709       orntNew[3] = -2;
5710       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
5711       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
5712 #if defined(PETSC_USE_DEBUG)
5713       if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+1, fStartNew, fEndNew);
5714       for (p = 0; p < 4; ++p) {
5715         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5716       }
5717 #endif
5718       /* C quad */
5719       coneNew[0] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
5720       orntNew[0] = ornt[1];
5721       coneNew[1] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
5722       orntNew[1] = ornt[2];
5723       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
5724       orntNew[2] = 0;
5725       coneNew[3] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
5726       orntNew[3] = -2;
5727       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
5728       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
5729 #if defined(PETSC_USE_DEBUG)
5730       if ((newp+2 < fStartNew) || (newp+2 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+2, fStartNew, fEndNew);
5731       for (p = 0; p < 4; ++p) {
5732         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5733       }
5734 #endif
5735       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
5736       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
5737       for (r = 0; r < 3; ++r) {
5738         for (s = 0; s < supportSize; ++s) {
5739           PetscInt subf;
5740 
5741           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
5742           if (coneSize != 5 && support[s] >= cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
5743           if (coneSize != 4 && support[s] <  cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
5744           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
5745           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
5746           for (c = 0; c < coneSize; ++c) {
5747             if (cone[c] == f) break;
5748           }
5749           subf = GetTriSubfaceInverse_Static(ornt[c], r);
5750           if (coneSize == 4) {
5751             supportRef[s] = cStartNew + (support[s] - cStart)*4 + faces[c*3+subf];
5752           } else if (coneSize == 5) {
5753             if (c != 0 && c != 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position %D in cone %D of cell %D (cMax %D) for face %D", c, support[s], cMax, f);
5754             supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*3 + subf;
5755           } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
5756         }
5757         ierr = DMPlexSetSupport(rdm, newp+r, supportRef);CHKERRQ(ierr);
5758 #if defined(PETSC_USE_DEBUG)
5759         if ((newp+r < fStartNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+r, fStartNew, fEndNew);
5760         for (p = 0; p < supportSize; ++p) {
5761           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
5762         }
5763 #endif
5764       }
5765     }
5766     /* Interior faces have 4 edges and 2 cells */
5767     for (c = cStart; c < cMax; ++c) {
5768       PetscInt        newp = fStartNew + (fMax - fStart)*3 + (c - cStart)*6;
5769       const PetscInt *cone, *ornt;
5770       PetscInt        coneNew[4], orntNew[4];
5771       PetscInt        supportNew[2];
5772 
5773       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
5774 #if defined(PETSC_USE_DEBUG)
5775       for (p = 0; p < 4; ++p) {
5776         if (cone[p] >= fMax) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position %D for face %D", cone[p], p, fMax, f);
5777       }
5778 #endif
5779       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
5780       /* Face {a, g, m, h} */
5781       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],0);
5782       orntNew[0] = 0;
5783       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 0;
5784       orntNew[1] = 0;
5785       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 1;
5786       orntNew[2] = -2;
5787       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],2);
5788       orntNew[3] = -2;
5789       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5790       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
5791 #if defined(PETSC_USE_DEBUG)
5792       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5793       for (p = 0; p < 4; ++p) {
5794         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5795       }
5796 #endif
5797       supportNew[0] = cStartNew + (c - cStart)*4 + 0;
5798       supportNew[1] = cStartNew + (c - cStart)*4 + 1;
5799       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5800 #if defined(PETSC_USE_DEBUG)
5801       for (p = 0; p < 2; ++p) {
5802         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5803       }
5804 #endif
5805       ++newp;
5806       /* Face {g, b, l , m} */
5807       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],1);
5808       orntNew[0] = -2;
5809       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],0);
5810       orntNew[1] = 0;
5811       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 3;
5812       orntNew[2] = 0;
5813       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 0;
5814       orntNew[3] = -2;
5815       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5816       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
5817 #if defined(PETSC_USE_DEBUG)
5818       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5819       for (p = 0; p < 4; ++p) {
5820         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5821       }
5822 #endif
5823       supportNew[0] = cStartNew + (c - cStart)*4 + 1;
5824       supportNew[1] = cStartNew + (c - cStart)*4 + 2;
5825       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5826 #if defined(PETSC_USE_DEBUG)
5827       for (p = 0; p < 2; ++p) {
5828         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5829       }
5830 #endif
5831       ++newp;
5832       /* Face {c, g, m, i} */
5833       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],2);
5834       orntNew[0] = 0;
5835       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 0;
5836       orntNew[1] = 0;
5837       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 2;
5838       orntNew[2] = -2;
5839       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],0);
5840       orntNew[3] = -2;
5841       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5842       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
5843 #if defined(PETSC_USE_DEBUG)
5844       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5845       for (p = 0; p < 4; ++p) {
5846         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5847       }
5848 #endif
5849       supportNew[0] = cStartNew + (c - cStart)*4 + 0;
5850       supportNew[1] = cStartNew + (c - cStart)*4 + 2;
5851       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5852 #if defined(PETSC_USE_DEBUG)
5853       for (p = 0; p < 2; ++p) {
5854         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5855       }
5856 #endif
5857       ++newp;
5858       /* Face {d, h, m, i} */
5859       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],0);
5860       orntNew[0] = 0;
5861       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 1;
5862       orntNew[1] = 0;
5863       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 2;
5864       orntNew[2] = -2;
5865       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],2);
5866       orntNew[3] = -2;
5867       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5868       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
5869 #if defined(PETSC_USE_DEBUG)
5870       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5871       for (p = 0; p < 4; ++p) {
5872         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5873       }
5874 #endif
5875       supportNew[0] = cStartNew + (c - cStart)*4 + 0;
5876       supportNew[1] = cStartNew + (c - cStart)*4 + 3;
5877       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5878 #if defined(PETSC_USE_DEBUG)
5879       for (p = 0; p < 2; ++p) {
5880         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5881       }
5882 #endif
5883       ++newp;
5884       /* Face {h, m, l, e} */
5885       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 1;
5886       orntNew[0] = 0;
5887       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 3;
5888       orntNew[1] = -2;
5889       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],1);
5890       orntNew[2] = -2;
5891       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],1);
5892       orntNew[3] = 0;
5893       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5894       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
5895 #if defined(PETSC_USE_DEBUG)
5896       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5897       for (p = 0; p < 4; ++p) {
5898         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5899       }
5900 #endif
5901       supportNew[0] = cStartNew + (c - cStart)*4 + 1;
5902       supportNew[1] = cStartNew + (c - cStart)*4 + 3;
5903       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5904 #if defined(PETSC_USE_DEBUG)
5905       for (p = 0; p < 2; ++p) {
5906         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5907       }
5908 #endif
5909       ++newp;
5910       /* Face {i, m, l, f} */
5911       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 2;
5912       orntNew[0] = 0;
5913       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 3;
5914       orntNew[1] = -2;
5915       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],2);
5916       orntNew[2] = -2;
5917       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],1);
5918       orntNew[3] = 0;
5919       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5920       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
5921 #if defined(PETSC_USE_DEBUG)
5922       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5923       for (p = 0; p < 4; ++p) {
5924         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5925       }
5926 #endif
5927       supportNew[0] = cStartNew + (c - cStart)*4 + 2;
5928       supportNew[1] = cStartNew + (c - cStart)*4 + 3;
5929       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5930 #if defined(PETSC_USE_DEBUG)
5931       for (p = 0; p < 2; ++p) {
5932         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5933       }
5934 #endif
5935       ++newp;
5936     }
5937     /* Hybrid split faces have 4 edges and same cells */
5938     for (f = fMax; f < fEnd; ++f) {
5939       const PetscInt *cone, *ornt, *support;
5940       PetscInt        coneNew[4], orntNew[4];
5941       PetscInt        size, s;
5942       const PetscInt  newp = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (f - fMax)*2;
5943 
5944       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
5945 #if defined(PETSC_USE_DEBUG)
5946       if (cone[0] >= eMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid edge %D (eMax %D) in cone position 0 for face %D", cone[0], eMax, f);
5947       if (cone[1] >= eMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid edge %D (eMax %D) in cone position 1 for face %D", cone[1], eMax, f);
5948       if (cone[2] <  eMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected edge %D (eMax %D) in cone position 2 for face %D", cone[2], eMax, f);
5949       if (cone[3] <  eMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected edge %D (eMax %D) in cone position 3 for face %D", cone[3], eMax, f);
5950 #endif
5951       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
5952       /* A face */
5953       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
5954       orntNew[0] = ornt[0];
5955       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (f - fMax);
5956       orntNew[1] = 0;
5957       coneNew[2] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
5958       orntNew[2] = ornt[1] < 0 ? 0 : -2;
5959       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (cone[2] - eMax);
5960       orntNew[3] = ornt[2] < 0 ? 0 : -2;
5961       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5962       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
5963 #if defined(PETSC_USE_DEBUG)
5964       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5965       for (p = 0; p < 4; ++p) {
5966         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5967       }
5968 #endif
5969 
5970       /* B face */
5971       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
5972       orntNew[0] = ornt[0];
5973       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (cone[3] - eMax);
5974       orntNew[1] = ornt[3];
5975       coneNew[2] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
5976       orntNew[2] = ornt[1] < 0 ? 0 : -2;
5977       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (f - fMax);
5978       orntNew[3] = -2;
5979       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
5980       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
5981 #if defined(PETSC_USE_DEBUG)
5982       if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+1, fStartNew, fEndNew);
5983       for (p = 0; p < 4; ++p) {
5984         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5985       }
5986 #endif
5987 
5988       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
5989       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
5990       for (r = 0; r < 2; ++r) {
5991         for (s = 0; s < size; ++s) {
5992           const PetscInt *coneCell, *orntCell, *fornt;
5993           PetscInt        coneSize, o, of, c;
5994 
5995           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
5996           if (coneSize != 5 || support[s] < cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
5997           ierr = DMPlexGetCone(dm, support[s], &coneCell);CHKERRQ(ierr);
5998           ierr = DMPlexGetConeOrientation(dm, support[s], &orntCell);CHKERRQ(ierr);
5999           o = orntCell[0] < 0 ? -1 : 1;
6000           for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
6001           if (c == 0 || c == 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position in cone %D of cell %D (cMax %D) for face %D", c, support[s], cMax, f);
6002           if (c == coneSize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %D in cone of cell %D", f, support[s]);
6003           ierr = DMPlexGetConeOrientation(dm, coneCell[0], &fornt);CHKERRQ(ierr);
6004           of = fornt[c-2] < 0 ? -1 : 1;
6005           supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*3 + (GetTriEdgeInverse_Static(orntCell[0], c-2) + (o*of < 0 ? 1-r : r))%3;
6006         }
6007         ierr = DMPlexSetSupport(rdm, newp + r, supportRef);CHKERRQ(ierr);
6008 #if defined(PETSC_USE_DEBUG)
6009         for (p = 0; p < size; ++p) {
6010           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
6011         }
6012 #endif
6013       }
6014     }
6015     /* Interior hybrid faces have 4 edges and 2 cells */
6016     for (c = cMax; c < cEnd; ++c) {
6017       PetscInt        newp = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3;
6018       const PetscInt *cone, *ornt;
6019       PetscInt        coneNew[4], orntNew[4];
6020       PetscInt        supportNew[2];
6021 
6022       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
6023 #if defined(PETSC_USE_DEBUG)
6024       if (cone[0] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position 0 for cell %D", cone[0], fMax, c);
6025       if (cone[1] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position 1 for cell %D", cone[1], fMax, c);
6026       if (cone[2] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected face %D (fMax %D) in cone position 2 for cell %D", cone[2], fMax, c);
6027       if (cone[3] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected face %D (fMax %D) in cone position 3 for cell %D", cone[3], fMax, c);
6028       if (cone[4] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected face %D (fMax %D) in cone position 3 for cell %D", cone[3], fMax, c);
6029 #endif
6030       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
6031       /* Face {a, g, h, d} */
6032       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],0);
6033       orntNew[0] = 0;
6034       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + c - cMax;
6035       orntNew[1] = 0;
6036       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],0);
6037       orntNew[2] = -2;
6038       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (cone[2] - fMax);
6039       orntNew[3] = -2;
6040       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6041       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6042 #if defined(PETSC_USE_DEBUG)
6043       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6044       for (p = 0; p < 4; ++p) {
6045         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6046       }
6047 #endif
6048       supportNew[0] = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + 0;
6049       supportNew[1] = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + 1;
6050       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
6051 #if defined(PETSC_USE_DEBUG)
6052       for (p = 0; p < 2; ++p) {
6053         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
6054       }
6055 #endif
6056       ++newp;
6057       /* Face {b, g, h, l} */
6058       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],1);
6059       orntNew[0] = 0;
6060       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + c - cMax;
6061       orntNew[1] = 0;
6062       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],1);
6063       orntNew[2] = -2;
6064       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (cone[3] - fMax);
6065       orntNew[3] = -2;
6066       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6067       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6068 #if defined(PETSC_USE_DEBUG)
6069       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6070       for (p = 0; p < 4; ++p) {
6071         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6072       }
6073 #endif
6074       supportNew[0] = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + 1;
6075       supportNew[1] = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + 2;
6076       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
6077 #if defined(PETSC_USE_DEBUG)
6078       for (p = 0; p < 2; ++p) {
6079         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
6080       }
6081 #endif
6082       ++newp;
6083       /* Face {c, g, h, f} */
6084       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],2);
6085       orntNew[0] = 0;
6086       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + c - cMax;
6087       orntNew[1] = 0;
6088       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],2);
6089       orntNew[2] = -2;
6090       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (cone[4] - fMax);
6091       orntNew[3] = -2;
6092       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6093       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6094 #if defined(PETSC_USE_DEBUG)
6095       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6096       for (p = 0; p < 4; ++p) {
6097         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6098       }
6099 #endif
6100       supportNew[0] = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + 2;
6101       supportNew[1] = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + 0;
6102       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
6103 #if defined(PETSC_USE_DEBUG)
6104       for (p = 0; p < 2; ++p) {
6105         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
6106       }
6107 #endif
6108     }
6109     /* Face edges have 2 vertices and 2 + cell faces supports */
6110     for (f = fStart; f < fMax; ++f) {
6111       const PetscInt *cone, *ornt, *support;
6112       PetscInt        coneSize, supportSize, s;
6113 
6114       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
6115       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
6116       for (r = 0; r < 3; ++r) {
6117         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
6118         PetscInt        coneNew[2];
6119         PetscInt        fint[4][3] = { {0, 1, 2},
6120                                        {3, 4, 0},
6121                                        {2, 5, 3},
6122                                        {1, 4, 5} };
6123 
6124         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
6125         if (cone[r] >= eMax) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected cone point %D in position %D for face %D (eMax %D)", cone[r], r, f, eMax);
6126         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
6127         coneNew[1] = vStartNew + (vEnd - vStart) + (eMax - eStart) + f - fStart;
6128         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6129 #if defined(PETSC_USE_DEBUG)
6130         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6131         for (p = 0; p < 2; ++p) {
6132           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
6133         }
6134 #endif
6135         supportRef[0] = fStartNew + (f - fStart)*3 + (r+0)%3;
6136         supportRef[1] = fStartNew + (f - fStart)*3 + (r+1)%3;
6137         for (s = 0; s < supportSize; ++s) {
6138           PetscInt er;
6139 
6140           supportRef[2+s] = -1;
6141           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
6142           if (coneSize != 5 && support[s] >= cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
6143           if (coneSize != 4 && support[s] <  cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
6144           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
6145           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
6146           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
6147           er = GetTriInteriorEdgeInverse_Static(ornt[c], r);
6148           if (coneSize == 4) {
6149             supportRef[2+s] = fStartNew + (fMax - fStart)*3 + (support[s] - cStart)*6 + fint[c][er];
6150           } else if (coneSize == 5) {
6151             if (c != 0 && c != 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position %D in cone %D of cell %D (cMax %D) for face %D", c, support[s], cMax, f);
6152             supportRef[2+s] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + er;
6153           }
6154         }
6155         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
6156 #if defined(PETSC_USE_DEBUG)
6157         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6158         for (p = 0; p < supportSize + 2; ++p) {
6159           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
6160         }
6161 #endif
6162       }
6163     }
6164     /* Interior cell edges have 2 vertices and 3 faces */
6165     for (c = cStart; c < cMax; ++c) {
6166       const PetscInt *cone;
6167       PetscInt       fint[4][3] = { {0,1,2},
6168                                     {0,3,4},
6169                                     {2,3,5},
6170                                     {1,4,5} } ;
6171 
6172       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
6173       for (r = 0; r < 4; r++) {
6174         PetscInt       coneNew[2], supportNew[3];
6175         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + r;
6176 
6177         if (cone[r] >= fMax) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position %D for cell %D", cone[r], r, fMax, c);
6178         coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[r] - fStart);
6179         coneNew[1] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax     -fStart) + c - cStart;
6180         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6181 #if defined(PETSC_USE_DEBUG)
6182         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6183         for (p = 0; p < 2; ++p) {
6184           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
6185         }
6186 #endif
6187         supportNew[0] = fStartNew + (fMax - fStart)*3 + (c - cStart)*6 + fint[r][0];
6188         supportNew[1] = fStartNew + (fMax - fStart)*3 + (c - cStart)*6 + fint[r][1];
6189         supportNew[2] = fStartNew + (fMax - fStart)*3 + (c - cStart)*6 + fint[r][2];
6190         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
6191 #if defined(PETSC_USE_DEBUG)
6192         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6193         for (p = 0; p < 3; ++p) {
6194           if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fEndNew);
6195         }
6196 #endif
6197       }
6198     }
6199     /* Hybrid edges have two vertices and the same faces */
6200     for (e = eMax; e < eEnd; ++e) {
6201       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (e - eMax);
6202       const PetscInt *cone, *support, *fcone;
6203       PetscInt        coneNew[2], size, fsize, s;
6204 
6205       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
6206       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
6207       ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
6208       coneNew[0] = vStartNew + (cone[0] - vStart);
6209       coneNew[1] = vStartNew + (cone[1] - vStart);
6210       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6211 #if defined(PETSC_USE_DEBUG)
6212       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is a edge [%D, %D)", newp, eStartNew, eEndNew);
6213       for (p = 0; p < 2; ++p) {
6214         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
6215       }
6216 #endif
6217       for (s = 0; s < size; ++s) {
6218         ierr = DMPlexGetConeSize(dm, support[s], &fsize);CHKERRQ(ierr);
6219         ierr = DMPlexGetCone(dm, support[s], &fcone);CHKERRQ(ierr);
6220         for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
6221         if ((c < 2) || (c > 3)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Edge %D not found in cone of face %D", e, support[s]);
6222         supportRef[s] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (support[s] - fMax)*2 + c-2;
6223       }
6224       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
6225 #if defined(PETSC_USE_DEBUG)
6226       for (p = 0; p < size; ++p) {
6227         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
6228       }
6229 #endif
6230     }
6231     /* Hybrid face edges have 2 vertices and 2 + cell faces supports */
6232     for (f = fMax; f < fEnd; ++f) {
6233       const PetscInt *cone, *ornt, *support;
6234       PetscInt        coneSize, supportSize;
6235       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + f - fMax;
6236       PetscInt        coneNew[2], s;
6237 
6238       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
6239 #if defined(PETSC_USE_DEBUG)
6240       if (cone[0] >= eMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected cone point %D in position 0 for face %D (eMax %D)", cone[0], f, eMax);
6241       if (cone[1] >= eMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected cone point %D in position 1 for face %D (eMax %D)", cone[1], f, eMax);
6242 #endif
6243       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
6244       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
6245       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6246 #if defined(PETSC_USE_DEBUG)
6247       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6248       for (p = 0; p < 2; ++p) {
6249         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
6250       }
6251 #endif
6252       supportRef[0] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (f- fMax)*2 + 0;
6253       supportRef[1] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (f- fMax)*2 + 1;
6254       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
6255       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
6256       for (s = 0; s < supportSize; ++s) {
6257         ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
6258         if (coneSize != 5 || support[s] < cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
6259         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
6260         ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
6261         for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
6262         if (c == 0 || c == 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position in cone %D of cell %D (cMax %D) for face %D", c, support[s], cMax, f);
6263         supportRef[2+s] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + c - 2;
6264       }
6265       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
6266 #if defined(PETSC_USE_DEBUG)
6267       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6268       for (p = 0; p < supportSize + 2; ++p) {
6269         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
6270       }
6271 #endif
6272     }
6273     /* Hybrid cell edges have 2 vertices and 3 faces */
6274     for (c = cMax; c < cEnd; ++c) {
6275       PetscInt       coneNew[2], supportNew[3];
6276       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + c - cMax;
6277       const PetscInt *cone;
6278 
6279       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
6280 #if defined(PETSC_USE_DEBUG)
6281       if (cone[0] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position 0 for cell %D", cone[0], fMax, c);
6282       if (cone[1] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position 1 for cell %D", cone[1], fMax, c);
6283 #endif
6284       coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[0] - fStart);
6285       coneNew[1] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[1] - fStart);
6286       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6287 #if defined(PETSC_USE_DEBUG)
6288       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6289       for (p = 0; p < 2; ++p) {
6290         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
6291       }
6292 #endif
6293       supportNew[0] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;
6294       supportNew[1] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;
6295       supportNew[2] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;
6296       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
6297 #if defined(PETSC_USE_DEBUG)
6298       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6299       for (p = 0; p < 3; ++p) {
6300         if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fEndNew);
6301       }
6302 #endif
6303     }
6304     /* Old vertices have identical supports */
6305     for (v = vStart; v < vEnd; ++v) {
6306       const PetscInt  newp = vStartNew + (v - vStart);
6307       const PetscInt *support, *cone;
6308       PetscInt        size, s;
6309 
6310       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
6311       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
6312       for (s = 0; s < size; ++s) {
6313         const PetscInt e = support[s];
6314 
6315         supportRef[s] = -1;
6316         if (eStart <= e) {
6317           if (e < eMax) {
6318             ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
6319             supportRef[s] = eStartNew + (e - eStart)*2 + (cone[1] == v ? 1 : 0);
6320           } else if (e < eEnd) {
6321             supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + e - eMax;
6322           } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", e, eStart, eEnd);
6323         } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", e, eStart, eEnd);
6324       }
6325       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
6326 #if defined(PETSC_USE_DEBUG)
6327       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
6328       for (p = 0; p < size; ++p) {
6329         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
6330       }
6331 #endif
6332     }
6333     /* Interior edge vertices have 2 + faces supports */
6334     for (e = eStart; e < eMax; ++e) {
6335       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
6336       const PetscInt *cone, *support;
6337       PetscInt        size, s;
6338 
6339       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
6340       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
6341       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
6342       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
6343       for (s = 0; s < size; ++s) {
6344         PetscInt r, coneSize;
6345 
6346         supportRef[2+s] = -1;
6347         ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
6348         if (coneSize != 4 && support[s] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for face %D (fMax %D)", coneSize, support[s], fMax);
6349         if (coneSize != 3 && support[s] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for face %D (fMax %D)", coneSize, support[s], fMax);
6350         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
6351         for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
6352         if (coneSize == 3) supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + r;
6353         else if (coneSize == 4) {
6354           if (r != 0 && r != 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position in cone %D of face %D (fMax %D) for edge %D", r, support[s], fMax, e);
6355           supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + support[s] - fMax;
6356         } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for face %D (fMax %D)", coneSize, support[s], fMax);
6357       }
6358       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
6359 #if defined(PETSC_USE_DEBUG)
6360       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
6361       for (p = 0; p < 2+size; ++p) {
6362         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
6363       }
6364 #endif
6365     }
6366     /* Split Edges have 2 vertices and the same faces as the parent */
6367     for (e = eStart; e < eMax; ++e) {
6368       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
6369 
6370       for (r = 0; r < 2; ++r) {
6371         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
6372         const PetscInt *cone, *ornt, *support;
6373         PetscInt        coneNew[2], coneSize, c, supportSize, s;
6374 
6375         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
6376         coneNew[0]       = vStartNew + (cone[0] - vStart);
6377         coneNew[1]       = vStartNew + (cone[1] - vStart);
6378         coneNew[(r+1)%2] = newv;
6379         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6380 #if defined(PETSC_USE_DEBUG)
6381         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6382         for (p = 0; p < 2; ++p) {
6383           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
6384         }
6385 #endif
6386         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
6387         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
6388         for (s = 0; s < supportSize; ++s) {
6389           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
6390           if (coneSize != 4 && support[s] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for face %D (fMax %D)", coneSize, support[s], fMax);
6391           if (coneSize != 3 && support[s] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for face %D (fMax %D)", coneSize, support[s], fMax);
6392           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
6393           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
6394           for (c = 0; c < coneSize; ++c) {
6395             if (cone[c] == e) break;
6396           }
6397           if (coneSize == 3) supportRef[s] = fStartNew + (support[s] - fStart)*3 + (c + (ornt[c] < 0 ? 1-r : r))%3;
6398           else if (coneSize == 4) {
6399             if (c != 0 && c != 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position in cone %D of face %D (fMax %D) for edge %D", c, support[s], fMax, e);
6400             supportRef[s] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
6401           } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for face %D (fMax %D)", coneSize, support[s], fMax);
6402         }
6403         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
6404 #if defined(PETSC_USE_DEBUG)
6405         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6406         for (p = 0; p < supportSize; ++p) {
6407           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
6408         }
6409 #endif
6410       }
6411     }
6412     /* Face vertices have 3 + cells supports */
6413     for (f = fStart; f < fMax; ++f) {
6414       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
6415       const PetscInt *cone, *support;
6416       PetscInt        size, s;
6417 
6418       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
6419       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
6420       supportRef[0] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 0;
6421       supportRef[1] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 1;
6422       supportRef[2] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 2;
6423       for (s = 0; s < size; ++s) {
6424         PetscInt r, coneSize;
6425 
6426         supportRef[3+s] = -1;
6427         ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
6428         if (coneSize != 5 && support[s] >= cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
6429         if (coneSize != 4 && support[s] <  cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
6430         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
6431         for (r = 0; r < coneSize; ++r) {if (cone[r] == f) break;}
6432         if (coneSize == 4) supportRef[3+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (support[s] - cStart)*4 + r;
6433         else if (coneSize == 5) {
6434           if (r != 0 && r != 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position in cone %D of cell %D (cMax %D) for face %D", r, support[s], cMax, f);
6435           supportRef[3+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + support[s] - cMax;
6436         }
6437       }
6438       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
6439 #if defined(PETSC_USE_DEBUG)
6440       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
6441       for (p = 0; p < 3+size; ++p) {
6442         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
6443       }
6444 #endif
6445     }
6446     /* Interior cell vertices have 4 supports */
6447     for (c = cStart; c < cMax; ++c) {
6448       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + c - cStart;
6449 
6450       supportRef[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 0;
6451       supportRef[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 1;
6452       supportRef[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 2;
6453       supportRef[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 3;
6454       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
6455 #if defined(PETSC_USE_DEBUG)
6456       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
6457       for (p = 0; p < 4; ++p) {
6458         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
6459       }
6460 #endif
6461     }
6462     ierr = PetscFree(supportRef);CHKERRQ(ierr);
6463     ierr = DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);CHKERRQ(ierr);
6464     break;
6465   case REFINER_HEX_3D:
6466     /*
6467      Bottom (viewed from top)    Top
6468      1---------2---------2       7---------2---------6
6469      |         |         |       |         |         |
6470      |    B    2    C    |       |    H    2    G    |
6471      |         |         |       |         |         |
6472      3----3----0----1----1       3----3----0----1----1
6473      |         |         |       |         |         |
6474      |    A    0    D    |       |    E    0    F    |
6475      |         |         |       |         |         |
6476      0---------0---------3       4---------0---------5
6477      */
6478     /* All cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
6479     for (c = cStart; c < cEnd; ++c) {
6480       const PetscInt  newp = (c - cStart)*8;
6481       const PetscInt *cone, *ornt;
6482       PetscInt        coneNew[6], orntNew[6];
6483 
6484       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
6485       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
6486       /* A hex */
6487       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
6488       orntNew[0] = ornt[0];
6489       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
6490       orntNew[1] = 0;
6491       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
6492       orntNew[2] = ornt[2];
6493       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
6494       orntNew[3] = 0;
6495       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
6496       orntNew[4] = 0;
6497       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
6498       orntNew[5] = ornt[5];
6499       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
6500       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
6501 #if defined(PETSC_USE_DEBUG)
6502       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
6503       for (p = 0; p < 6; ++p) {
6504         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6505       }
6506 #endif
6507       /* B hex */
6508       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
6509       orntNew[0] = ornt[0];
6510       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
6511       orntNew[1] = 0;
6512       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
6513       orntNew[2] = -1;
6514       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
6515       orntNew[3] = ornt[3];
6516       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
6517       orntNew[4] = 0;
6518       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
6519       orntNew[5] = ornt[5];
6520       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
6521       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
6522 #if defined(PETSC_USE_DEBUG)
6523       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
6524       for (p = 0; p < 6; ++p) {
6525         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6526       }
6527 #endif
6528       /* C hex */
6529       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
6530       orntNew[0] = ornt[0];
6531       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
6532       orntNew[1] = 0;
6533       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
6534       orntNew[2] = -1;
6535       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
6536       orntNew[3] = ornt[3];
6537       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
6538       orntNew[4] = ornt[4];
6539       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
6540       orntNew[5] = -4;
6541       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
6542       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
6543 #if defined(PETSC_USE_DEBUG)
6544       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
6545       for (p = 0; p < 6; ++p) {
6546         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6547       }
6548 #endif
6549       /* D hex */
6550       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
6551       orntNew[0] = ornt[0];
6552       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
6553       orntNew[1] = 0;
6554       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
6555       orntNew[2] = ornt[2];
6556       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
6557       orntNew[3] = 0;
6558       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
6559       orntNew[4] = ornt[4];
6560       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
6561       orntNew[5] = -4;
6562       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
6563       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
6564 #if defined(PETSC_USE_DEBUG)
6565       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
6566       for (p = 0; p < 6; ++p) {
6567         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6568       }
6569 #endif
6570       /* E hex */
6571       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
6572       orntNew[0] = -4;
6573       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
6574       orntNew[1] = ornt[1];
6575       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
6576       orntNew[2] = ornt[2];
6577       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
6578       orntNew[3] = 0;
6579       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
6580       orntNew[4] = -1;
6581       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
6582       orntNew[5] = ornt[5];
6583       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
6584       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
6585 #if defined(PETSC_USE_DEBUG)
6586       if ((newp+4 < cStartNew) || (newp+4 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+4, cStartNew, cEndNew);
6587       for (p = 0; p < 6; ++p) {
6588         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6589       }
6590 #endif
6591       /* F hex */
6592       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
6593       orntNew[0] = -4;
6594       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
6595       orntNew[1] = ornt[1];
6596       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
6597       orntNew[2] = ornt[2];
6598       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
6599       orntNew[3] = -1;
6600       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
6601       orntNew[4] = ornt[4];
6602       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
6603       orntNew[5] = 1;
6604       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
6605       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
6606 #if defined(PETSC_USE_DEBUG)
6607       if ((newp+5 < cStartNew) || (newp+5 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+5, cStartNew, cEndNew);
6608       for (p = 0; p < 6; ++p) {
6609         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6610       }
6611 #endif
6612       /* G hex */
6613       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
6614       orntNew[0] = -4;
6615       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
6616       orntNew[1] = ornt[1];
6617       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
6618       orntNew[2] = 0;
6619       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
6620       orntNew[3] = ornt[3];
6621       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
6622       orntNew[4] = ornt[4];
6623       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
6624       orntNew[5] = -3;
6625       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
6626       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
6627 #if defined(PETSC_USE_DEBUG)
6628       if ((newp+6 < cStartNew) || (newp+6 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+6, cStartNew, cEndNew);
6629       for (p = 0; p < 6; ++p) {
6630         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6631       }
6632 #endif
6633       /* H hex */
6634       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
6635       orntNew[0] = -4;
6636       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
6637       orntNew[1] = ornt[1];
6638       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
6639       orntNew[2] = -1;
6640       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
6641       orntNew[3] = ornt[3];
6642       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
6643       orntNew[4] = 3;
6644       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
6645       orntNew[5] = ornt[5];
6646       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
6647       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
6648 #if defined(PETSC_USE_DEBUG)
6649       if ((newp+7 < cStartNew) || (newp+7 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+7, cStartNew, cEndNew);
6650       for (p = 0; p < 6; ++p) {
6651         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6652       }
6653 #endif
6654     }
6655     /* Split faces have 4 edges and the same cells as the parent */
6656     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
6657     ierr = PetscMalloc1(4 + maxSupportSize*2, &supportRef);CHKERRQ(ierr);
6658     for (f = fStart; f < fEnd; ++f) {
6659       for (r = 0; r < 4; ++r) {
6660         /* TODO: This can come from GetFaces_Internal() */
6661         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};
6662         const PetscInt  newp = fStartNew + (f - fStart)*4 + r;
6663         const PetscInt *cone, *ornt, *support;
6664         PetscInt        coneNew[4], orntNew[4], coneSize, c, supportSize, s;
6665 
6666         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
6667         ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
6668         coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
6669         orntNew[(r+3)%4] = ornt[(r+3)%4];
6670         coneNew[(r+0)%4] = eStartNew + (cone[r]       - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
6671         orntNew[(r+0)%4] = ornt[r];
6672         coneNew[(r+1)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
6673         orntNew[(r+1)%4] = 0;
6674         coneNew[(r+2)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + (r+3)%4;
6675         orntNew[(r+2)%4] = -2;
6676         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6677         ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6678 #if defined(PETSC_USE_DEBUG)
6679         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6680         for (p = 0; p < 4; ++p) {
6681           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6682         }
6683 #endif
6684         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
6685         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
6686         for (s = 0; s < supportSize; ++s) {
6687           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
6688           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
6689           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
6690           for (c = 0; c < coneSize; ++c) {
6691             if (cone[c] == f) break;
6692           }
6693           supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+GetQuadSubfaceInverse_Static(ornt[c], r)];
6694         }
6695         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
6696 #if defined(PETSC_USE_DEBUG)
6697         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6698         for (p = 0; p < supportSize; ++p) {
6699           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
6700         }
6701 #endif
6702       }
6703     }
6704     /* Interior faces have 4 edges and 2 cells */
6705     for (c = cStart; c < cEnd; ++c) {
6706       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};
6707       const PetscInt *cone, *ornt;
6708       PetscInt        newp, coneNew[4], orntNew[4], supportNew[2];
6709 
6710       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
6711       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
6712       /* A-D face */
6713       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0;
6714       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
6715       orntNew[0] = 0;
6716       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
6717       orntNew[1] = 0;
6718       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
6719       orntNew[2] = -2;
6720       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
6721       orntNew[3] = -2;
6722       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6723       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6724 #if defined(PETSC_USE_DEBUG)
6725       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6726       for (p = 0; p < 4; ++p) {
6727         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6728       }
6729 #endif
6730       /* C-D face */
6731       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1;
6732       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
6733       orntNew[0] = 0;
6734       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
6735       orntNew[1] = 0;
6736       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
6737       orntNew[2] = -2;
6738       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
6739       orntNew[3] = -2;
6740       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6741       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6742 #if defined(PETSC_USE_DEBUG)
6743       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6744       for (p = 0; p < 4; ++p) {
6745         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6746       }
6747 #endif
6748       /* B-C face */
6749       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2;
6750       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
6751       orntNew[0] = -2;
6752       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
6753       orntNew[1] = 0;
6754       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
6755       orntNew[2] = 0;
6756       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
6757       orntNew[3] = -2;
6758       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6759       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6760 #if defined(PETSC_USE_DEBUG)
6761       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6762       for (p = 0; p < 4; ++p) {
6763         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6764       }
6765 #endif
6766       /* A-B face */
6767       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3;
6768       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
6769       orntNew[0] = -2;
6770       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
6771       orntNew[1] = 0;
6772       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
6773       orntNew[2] = 0;
6774       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
6775       orntNew[3] = -2;
6776       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6777       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6778 #if defined(PETSC_USE_DEBUG)
6779       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6780       for (p = 0; p < 4; ++p) {
6781         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6782       }
6783 #endif
6784       /* E-F face */
6785       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4;
6786       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
6787       orntNew[0] = -2;
6788       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
6789       orntNew[1] = -2;
6790       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
6791       orntNew[2] = 0;
6792       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
6793       orntNew[3] = 0;
6794       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6795       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6796 #if defined(PETSC_USE_DEBUG)
6797       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6798       for (p = 0; p < 4; ++p) {
6799         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6800       }
6801 #endif
6802       /* F-G face */
6803       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5;
6804       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
6805       orntNew[0] = -2;
6806       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
6807       orntNew[1] = -2;
6808       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
6809       orntNew[2] = 0;
6810       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
6811       orntNew[3] = 0;
6812       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6813       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6814 #if defined(PETSC_USE_DEBUG)
6815       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6816       for (p = 0; p < 4; ++p) {
6817         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6818       }
6819 #endif
6820       /* G-H face */
6821       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6;
6822       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
6823       orntNew[0] = -2;
6824       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
6825       orntNew[1] = 0;
6826       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
6827       orntNew[2] = 0;
6828       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
6829       orntNew[3] = -2;
6830       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6831       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6832 #if defined(PETSC_USE_DEBUG)
6833       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6834       for (p = 0; p < 4; ++p) {
6835         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6836       }
6837 #endif
6838       /* E-H face */
6839       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7;
6840       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
6841       orntNew[0] = -2;
6842       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
6843       orntNew[1] = -2;
6844       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
6845       orntNew[2] = 0;
6846       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
6847       orntNew[3] = 0;
6848       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6849       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6850 #if defined(PETSC_USE_DEBUG)
6851       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6852       for (p = 0; p < 4; ++p) {
6853         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6854       }
6855 #endif
6856       /* A-E face */
6857       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8;
6858       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
6859       orntNew[0] = 0;
6860       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
6861       orntNew[1] = 0;
6862       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
6863       orntNew[2] = -2;
6864       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
6865       orntNew[3] = -2;
6866       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6867       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6868 #if defined(PETSC_USE_DEBUG)
6869       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6870       for (p = 0; p < 4; ++p) {
6871         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6872       }
6873 #endif
6874       /* D-F face */
6875       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9;
6876       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
6877       orntNew[0] = -2;
6878       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
6879       orntNew[1] = 0;
6880       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
6881       orntNew[2] = 0;
6882       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
6883       orntNew[3] = -2;
6884       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6885       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6886 #if defined(PETSC_USE_DEBUG)
6887       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6888       for (p = 0; p < 4; ++p) {
6889         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6890       }
6891 #endif
6892       /* C-G face */
6893       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10;
6894       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
6895       orntNew[0] = -2;
6896       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
6897       orntNew[1] = -2;
6898       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
6899       orntNew[2] = 0;
6900       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
6901       orntNew[3] = 0;
6902       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6903       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6904 #if defined(PETSC_USE_DEBUG)
6905       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6906       for (p = 0; p < 4; ++p) {
6907         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6908       }
6909 #endif
6910       /* B-H face */
6911       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11;
6912       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
6913       orntNew[0] = 0;
6914       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
6915       orntNew[1] = -2;
6916       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
6917       orntNew[2] = -2;
6918       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
6919       orntNew[3] = 0;
6920       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6921       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
6922 #if defined(PETSC_USE_DEBUG)
6923       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6924       for (p = 0; p < 4; ++p) {
6925         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6926       }
6927 #endif
6928       for (r = 0; r < 12; ++r) {
6929         newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
6930         supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
6931         supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
6932         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
6933 #if defined(PETSC_USE_DEBUG)
6934         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6935         for (p = 0; p < 2; ++p) {
6936           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
6937         }
6938 #endif
6939       }
6940     }
6941     /* Split edges have 2 vertices and the same faces as the parent */
6942     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
6943     for (e = eStart; e < eEnd; ++e) {
6944       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
6945 
6946       for (r = 0; r < 2; ++r) {
6947         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
6948         const PetscInt *cone, *ornt, *support;
6949         PetscInt        coneNew[2], coneSize, c, supportSize, s;
6950 
6951         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
6952         coneNew[0]       = vStartNew + (cone[0] - vStart);
6953         coneNew[1]       = vStartNew + (cone[1] - vStart);
6954         coneNew[(r+1)%2] = newv;
6955         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6956 #if defined(PETSC_USE_DEBUG)
6957         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6958         for (p = 0; p < 2; ++p) {
6959           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
6960         }
6961 #endif
6962         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
6963         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
6964         for (s = 0; s < supportSize; ++s) {
6965           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
6966           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
6967           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
6968           for (c = 0; c < coneSize; ++c) {
6969             if (cone[c] == e) break;
6970           }
6971           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
6972         }
6973         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
6974 #if defined(PETSC_USE_DEBUG)
6975         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6976         for (p = 0; p < supportSize; ++p) {
6977           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
6978         }
6979 #endif
6980       }
6981     }
6982     /* Face edges have 2 vertices and 2+cells faces */
6983     for (f = fStart; f < fEnd; ++f) {
6984       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};
6985       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
6986       const PetscInt *cone, *coneCell, *orntCell, *support;
6987       PetscInt        coneNew[2], coneSize, c, supportSize, s;
6988 
6989       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
6990       for (r = 0; r < 4; ++r) {
6991         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
6992 
6993         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
6994         coneNew[1] = newv;
6995         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
6996 #if defined(PETSC_USE_DEBUG)
6997         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6998         for (p = 0; p < 2; ++p) {
6999           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
7000         }
7001 #endif
7002         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
7003         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
7004         supportRef[0] = fStartNew + (f - fStart)*4 + r;
7005         supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
7006         for (s = 0; s < supportSize; ++s) {
7007           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
7008           ierr = DMPlexGetCone(dm, support[s], &coneCell);CHKERRQ(ierr);
7009           ierr = DMPlexGetConeOrientation(dm, support[s], &orntCell);CHKERRQ(ierr);
7010           for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
7011           supportRef[2+s] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
7012         }
7013         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
7014 #if defined(PETSC_USE_DEBUG)
7015         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
7016         for (p = 0; p < 2+supportSize; ++p) {
7017           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
7018         }
7019 #endif
7020       }
7021     }
7022     /* Cell edges have 2 vertices and 4 faces */
7023     for (c = cStart; c < cEnd; ++c) {
7024       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};
7025       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
7026       const PetscInt *cone;
7027       PetscInt        coneNew[2], supportNew[4];
7028 
7029       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
7030       for (r = 0; r < 6; ++r) {
7031         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
7032 
7033         coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
7034         coneNew[1] = newv;
7035         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7036 #if defined(PETSC_USE_DEBUG)
7037         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
7038         for (p = 0; p < 2; ++p) {
7039           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
7040         }
7041 #endif
7042         for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
7043         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
7044 #if defined(PETSC_USE_DEBUG)
7045         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
7046         for (p = 0; p < 4; ++p) {
7047           if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fEndNew);
7048         }
7049 #endif
7050       }
7051     }
7052     /* Old vertices have identical supports */
7053     for (v = vStart; v < vEnd; ++v) {
7054       const PetscInt  newp = vStartNew + (v - vStart);
7055       const PetscInt *support, *cone;
7056       PetscInt        size, s;
7057 
7058       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
7059       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
7060       for (s = 0; s < size; ++s) {
7061         PetscInt r = 0;
7062 
7063         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
7064         if (cone[1] == v) r = 1;
7065         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
7066       }
7067       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
7068 #if defined(PETSC_USE_DEBUG)
7069       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
7070       for (p = 0; p < size; ++p) {
7071         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
7072       }
7073 #endif
7074     }
7075     /* Edge vertices have 2 + faces supports */
7076     for (e = eStart; e < eEnd; ++e) {
7077       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
7078       const PetscInt *cone, *support;
7079       PetscInt        size, s;
7080 
7081       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
7082       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
7083       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
7084       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
7085       for (s = 0; s < size; ++s) {
7086         PetscInt r;
7087 
7088         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
7089         for (r = 0; r < 4; ++r) if (cone[r] == e) break;
7090         supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*4 + r;
7091       }
7092       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
7093 #if defined(PETSC_USE_DEBUG)
7094       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
7095       for (p = 0; p < 2+size; ++p) {
7096         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
7097       }
7098 #endif
7099     }
7100     /* Face vertices have 4 + cells supports */
7101     for (f = fStart; f < fEnd; ++f) {
7102       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
7103       const PetscInt *cone, *support;
7104       PetscInt        size, s;
7105 
7106       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
7107       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
7108       for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eEnd - eStart)*2 +  (f - fStart)*4 + r;
7109       for (s = 0; s < size; ++s) {
7110         PetscInt r;
7111 
7112         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
7113         for (r = 0; r < 6; ++r) if (cone[r] == f) break;
7114         supportRef[4+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (support[s] - cStart)*6 + r;
7115       }
7116       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
7117 #if defined(PETSC_USE_DEBUG)
7118       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
7119       for (p = 0; p < 4+size; ++p) {
7120         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
7121       }
7122 #endif
7123     }
7124     /* Cell vertices have 6 supports */
7125     for (c = cStart; c < cEnd; ++c) {
7126       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
7127       PetscInt       supportNew[6];
7128 
7129       for (r = 0; r < 6; ++r) {
7130         supportNew[r] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
7131       }
7132       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
7133     }
7134     ierr = PetscFree(supportRef);CHKERRQ(ierr);
7135     break;
7136   case REFINER_HYBRID_HEX_3D:
7137     ierr = DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);CHKERRQ(ierr);
7138     /*
7139      Bottom (viewed from top)    Top
7140      1---------2---------2       7---------2---------6
7141      |         |         |       |         |         |
7142      |    B    2    C    |       |    H    2    G    |
7143      |         |         |       |         |         |
7144      3----3----0----1----1       3----3----0----1----1
7145      |         |         |       |         |         |
7146      |    A    0    D    |       |    E    0    F    |
7147      |         |         |       |         |         |
7148      0---------0---------3       4---------0---------5
7149      */
7150     /* Interior cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
7151     for (c = cStart; c < cMax; ++c) {
7152       const PetscInt  newp = (c - cStart)*8;
7153       const PetscInt *cone, *ornt;
7154       PetscInt        coneNew[6], orntNew[6];
7155 
7156       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
7157       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
7158       /* A hex */
7159       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
7160       orntNew[0] = ornt[0];
7161       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
7162       orntNew[1] = 0;
7163       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
7164       orntNew[2] = ornt[2];
7165       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
7166       orntNew[3] = 0;
7167       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
7168       orntNew[4] = 0;
7169       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
7170       orntNew[5] = ornt[5];
7171       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
7172       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
7173 #if defined(PETSC_USE_DEBUG)
7174       if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cMaxNew);
7175       for (p = 0; p < 6; ++p) {
7176         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7177       }
7178 #endif
7179       /* B hex */
7180       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
7181       orntNew[0] = ornt[0];
7182       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
7183       orntNew[1] = 0;
7184       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
7185       orntNew[2] = -1;
7186       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
7187       orntNew[3] = ornt[3];
7188       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
7189       orntNew[4] = 0;
7190       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
7191       orntNew[5] = ornt[5];
7192       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
7193       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
7194 #if defined(PETSC_USE_DEBUG)
7195       if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cMaxNew);
7196       for (p = 0; p < 6; ++p) {
7197         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7198       }
7199 #endif
7200       /* C hex */
7201       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
7202       orntNew[0] = ornt[0];
7203       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
7204       orntNew[1] = 0;
7205       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
7206       orntNew[2] = -1;
7207       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
7208       orntNew[3] = ornt[3];
7209       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
7210       orntNew[4] = ornt[4];
7211       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
7212       orntNew[5] = -4;
7213       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
7214       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
7215 #if defined(PETSC_USE_DEBUG)
7216       if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cMaxNew);
7217       for (p = 0; p < 6; ++p) {
7218         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7219       }
7220 #endif
7221       /* D hex */
7222       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
7223       orntNew[0] = ornt[0];
7224       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
7225       orntNew[1] = 0;
7226       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
7227       orntNew[2] = ornt[2];
7228       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
7229       orntNew[3] = 0;
7230       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
7231       orntNew[4] = ornt[4];
7232       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
7233       orntNew[5] = -4;
7234       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
7235       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
7236 #if defined(PETSC_USE_DEBUG)
7237       if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cMaxNew);
7238       for (p = 0; p < 6; ++p) {
7239         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7240       }
7241 #endif
7242       /* E hex */
7243       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
7244       orntNew[0] = -4;
7245       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
7246       orntNew[1] = ornt[1];
7247       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
7248       orntNew[2] = ornt[2];
7249       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
7250       orntNew[3] = 0;
7251       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
7252       orntNew[4] = -1;
7253       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
7254       orntNew[5] = ornt[5];
7255       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
7256       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
7257 #if defined(PETSC_USE_DEBUG)
7258       if ((newp+4 < cStartNew) || (newp+4 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+4, cStartNew, cMaxNew);
7259       for (p = 0; p < 6; ++p) {
7260         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7261       }
7262 #endif
7263       /* F hex */
7264       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
7265       orntNew[0] = -4;
7266       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
7267       orntNew[1] = ornt[1];
7268       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
7269       orntNew[2] = ornt[2];
7270       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
7271       orntNew[3] = -1;
7272       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
7273       orntNew[4] = ornt[4];
7274       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
7275       orntNew[5] = 1;
7276       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
7277       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
7278 #if defined(PETSC_USE_DEBUG)
7279       if ((newp+5 < cStartNew) || (newp+5 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+5, cStartNew, cMaxNew);
7280       for (p = 0; p < 6; ++p) {
7281         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7282       }
7283 #endif
7284       /* G hex */
7285       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
7286       orntNew[0] = -4;
7287       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
7288       orntNew[1] = ornt[1];
7289       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
7290       orntNew[2] = 0;
7291       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
7292       orntNew[3] = ornt[3];
7293       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
7294       orntNew[4] = ornt[4];
7295       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
7296       orntNew[5] = -3;
7297       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
7298       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
7299 #if defined(PETSC_USE_DEBUG)
7300       if ((newp+6 < cStartNew) || (newp+6 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+6, cStartNew, cMaxNew);
7301       for (p = 0; p < 6; ++p) {
7302         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7303       }
7304 #endif
7305       /* H hex */
7306       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
7307       orntNew[0] = -4;
7308       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
7309       orntNew[1] = ornt[1];
7310       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
7311       orntNew[2] = -1;
7312       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
7313       orntNew[3] = ornt[3];
7314       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
7315       orntNew[4] = 3;
7316       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
7317       orntNew[5] = ornt[5];
7318       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
7319       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
7320 #if defined(PETSC_USE_DEBUG)
7321       if ((newp+7 < cStartNew) || (newp+7 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+7, cStartNew, cMaxNew);
7322       for (p = 0; p < 6; ++p) {
7323         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7324       }
7325 #endif
7326     }
7327     /* Hybrid cells have 6 faces: Front, Back, Sides */
7328     /*
7329      3---------2---------2
7330      |         |         |
7331      |    D    2    C    |
7332      |         |         |
7333      3----3----0----1----1
7334      |         |         |
7335      |    A    0    B    |
7336      |         |         |
7337      0---------0---------1
7338      */
7339     for (c = cMax; c < cEnd; ++c) {
7340       const PetscInt  newp = (cMax - cStart)*8 + (c - cMax)*4;
7341       const PetscInt *cone, *ornt, *fornt;
7342       PetscInt        coneNew[6], orntNew[6], o, of, i;
7343 
7344       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
7345       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
7346       ierr = DMPlexGetConeOrientation(dm, cone[0], &fornt);CHKERRQ(ierr);
7347       o = ornt[0] < 0 ? -1 : 1;
7348       for (r = 0; r < 4; ++r) {
7349         PetscInt subfA = GetQuadSubface_Static(ornt[0], r);
7350         PetscInt edgeA = GetQuadEdge_Static(ornt[0], r);
7351         PetscInt edgeB = GetQuadEdge_Static(ornt[0], (r+3)%4);
7352         if (ornt[0] != ornt[1]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent ordering for matching ends of hybrid cell %D: %D != %D", c, ornt[0], ornt[1]);
7353         coneNew[0]         = fStartNew + (cone[0] - fStart)*4 + subfA;
7354         orntNew[0]         = ornt[0];
7355         coneNew[1]         = fStartNew + (cone[1] - fStart)*4 + subfA;
7356         orntNew[1]         = ornt[0];
7357         of = fornt[edgeA] < 0 ? -1 : 1;
7358         i  = GetQuadEdgeInverse_Static(ornt[0], r) + 2;
7359         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[2+edgeA] - fMax)*2 + (o*of < 0 ? 1 : 0);
7360         orntNew[i] = ornt[edgeA];
7361         i  = GetQuadEdgeInverse_Static(ornt[0], (r+1)%4) + 2;
7362         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd          - fMax)*2 + (c - cMax)*4 + edgeA;
7363         orntNew[i] = 0;
7364         i  = GetQuadEdgeInverse_Static(ornt[0], (r+2)%4) + 2;
7365         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd          - fMax)*2 + (c - cMax)*4 + edgeB;
7366         orntNew[i] = -2;
7367         of = fornt[edgeB] < 0 ? -1 : 1;
7368         i  = GetQuadEdgeInverse_Static(ornt[0], (r+3)%4) + 2;
7369         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[2+edgeB] - fMax)*2 + (o*of < 0 ? 0 : 1);
7370         orntNew[i] = ornt[edgeB];
7371         ierr       = DMPlexSetCone(rdm, newp+r, coneNew);CHKERRQ(ierr);
7372         ierr       = DMPlexSetConeOrientation(rdm, newp+r, orntNew);CHKERRQ(ierr);
7373 #if defined(PETSC_USE_DEBUG)
7374         if ((newp+r < cMaxNew) || (newp+r >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", newp+r, cMaxNew, cEndNew);
7375         for (p = 0; p < 2; ++p) {
7376           if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7377         }
7378         for (p = 2; p < 6; ++p) {
7379           if ((coneNew[p] < fMaxNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", coneNew[p], fMaxNew, fEndNew);
7380         }
7381 #endif
7382       }
7383     }
7384     /* Interior split faces have 4 edges and the same cells as the parent */
7385     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
7386     ierr = PetscMalloc1(4 + maxSupportSize*2, &supportRef);CHKERRQ(ierr);
7387     for (f = fStart; f < fMax; ++f) {
7388       for (r = 0; r < 4; ++r) {
7389         /* TODO: This can come from GetFaces_Internal() */
7390         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};
7391         const PetscInt  newp = fStartNew + (f - fStart)*4 + r;
7392         const PetscInt *cone, *ornt, *support;
7393         PetscInt        coneNew[4], orntNew[4], coneSize, c, supportSize, s;
7394 
7395         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
7396         ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
7397         coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
7398         orntNew[(r+3)%4] = ornt[(r+3)%4];
7399         coneNew[(r+0)%4] = eStartNew + (cone[r]       - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
7400         orntNew[(r+0)%4] = ornt[r];
7401         coneNew[(r+1)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
7402         orntNew[(r+1)%4] = 0;
7403         coneNew[(r+2)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + (r+3)%4;
7404         orntNew[(r+2)%4] = -2;
7405         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7406         ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7407 #if defined(PETSC_USE_DEBUG)
7408         if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7409         for (p = 0; p < 4; ++p) {
7410           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7411         }
7412 #endif
7413         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
7414         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
7415         for (s = 0; s < supportSize; ++s) {
7416           PetscInt subf;
7417           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
7418           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
7419           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
7420           for (c = 0; c < coneSize; ++c) {
7421             if (cone[c] == f) break;
7422           }
7423           subf = GetQuadSubfaceInverse_Static(ornt[c], r);
7424           if (support[s] < cMax) {
7425             supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+subf];
7426           } else {
7427             supportRef[s] = cStartNew + (cMax       - cStart)*8 + (support[s] - cMax)*4 + subf;
7428           }
7429         }
7430         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
7431 #if defined(PETSC_USE_DEBUG)
7432         if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7433         for (p = 0; p < supportSize; ++p) {
7434           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
7435         }
7436 #endif
7437       }
7438     }
7439     /* Interior cell faces have 4 edges and 2 cells */
7440     for (c = cStart; c < cMax; ++c) {
7441       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};
7442       const PetscInt *cone, *ornt;
7443       PetscInt        newp, coneNew[4], orntNew[4], supportNew[2];
7444 
7445       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
7446       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
7447       /* A-D face */
7448       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 0;
7449       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
7450       orntNew[0] = 0;
7451       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
7452       orntNew[1] = 0;
7453       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
7454       orntNew[2] = -2;
7455       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
7456       orntNew[3] = -2;
7457       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7458       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7459 #if defined(PETSC_USE_DEBUG)
7460       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7461       for (p = 0; p < 4; ++p) {
7462         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7463       }
7464 #endif
7465       /* C-D face */
7466       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 1;
7467       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
7468       orntNew[0] = 0;
7469       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
7470       orntNew[1] = 0;
7471       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
7472       orntNew[2] = -2;
7473       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
7474       orntNew[3] = -2;
7475       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7476       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7477 #if defined(PETSC_USE_DEBUG)
7478       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7479       for (p = 0; p < 4; ++p) {
7480         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7481       }
7482 #endif
7483       /* B-C face */
7484       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 2;
7485       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
7486       orntNew[0] = -2;
7487       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
7488       orntNew[1] = 0;
7489       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
7490       orntNew[2] = 0;
7491       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
7492       orntNew[3] = -2;
7493       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7494       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7495 #if defined(PETSC_USE_DEBUG)
7496       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7497       for (p = 0; p < 4; ++p) {
7498         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7499       }
7500 #endif
7501       /* A-B face */
7502       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 3;
7503       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
7504       orntNew[0] = -2;
7505       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
7506       orntNew[1] = 0;
7507       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
7508       orntNew[2] = 0;
7509       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
7510       orntNew[3] = -2;
7511       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7512       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7513 #if defined(PETSC_USE_DEBUG)
7514       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7515       for (p = 0; p < 4; ++p) {
7516         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7517       }
7518 #endif
7519       /* E-F face */
7520       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 4;
7521       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
7522       orntNew[0] = -2;
7523       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
7524       orntNew[1] = -2;
7525       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
7526       orntNew[2] = 0;
7527       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
7528       orntNew[3] = 0;
7529       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7530       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7531 #if defined(PETSC_USE_DEBUG)
7532       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7533       for (p = 0; p < 4; ++p) {
7534         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7535       }
7536 #endif
7537       /* F-G face */
7538       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 5;
7539       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
7540       orntNew[0] = -2;
7541       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
7542       orntNew[1] = -2;
7543       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
7544       orntNew[2] = 0;
7545       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
7546       orntNew[3] = 0;
7547       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7548       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7549 #if defined(PETSC_USE_DEBUG)
7550       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7551       for (p = 0; p < 4; ++p) {
7552         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7553       }
7554 #endif
7555       /* G-H face */
7556       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 6;
7557       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
7558       orntNew[0] = -2;
7559       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
7560       orntNew[1] = 0;
7561       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
7562       orntNew[2] = 0;
7563       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
7564       orntNew[3] = -2;
7565       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7566       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7567 #if defined(PETSC_USE_DEBUG)
7568       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7569       for (p = 0; p < 4; ++p) {
7570         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7571       }
7572 #endif
7573       /* E-H face */
7574       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 7;
7575       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
7576       orntNew[0] = -2;
7577       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
7578       orntNew[1] = -2;
7579       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
7580       orntNew[2] = 0;
7581       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
7582       orntNew[3] = 0;
7583       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7584       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7585 #if defined(PETSC_USE_DEBUG)
7586       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7587       for (p = 0; p < 4; ++p) {
7588         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7589       }
7590 #endif
7591       /* A-E face */
7592       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 8;
7593       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
7594       orntNew[0] = 0;
7595       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
7596       orntNew[1] = 0;
7597       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
7598       orntNew[2] = -2;
7599       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
7600       orntNew[3] = -2;
7601       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7602       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7603 #if defined(PETSC_USE_DEBUG)
7604       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7605       for (p = 0; p < 4; ++p) {
7606         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7607       }
7608 #endif
7609       /* D-F face */
7610       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 9;
7611       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
7612       orntNew[0] = -2;
7613       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
7614       orntNew[1] = 0;
7615       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
7616       orntNew[2] = 0;
7617       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
7618       orntNew[3] = -2;
7619       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7620       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7621 #if defined(PETSC_USE_DEBUG)
7622       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7623       for (p = 0; p < 4; ++p) {
7624         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7625       }
7626 #endif
7627       /* C-G face */
7628       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 10;
7629       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
7630       orntNew[0] = -2;
7631       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
7632       orntNew[1] = -2;
7633       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
7634       orntNew[2] = 0;
7635       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
7636       orntNew[3] = 0;
7637       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7638       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7639 #if defined(PETSC_USE_DEBUG)
7640       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7641       for (p = 0; p < 4; ++p) {
7642         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7643       }
7644 #endif
7645       /* B-H face */
7646       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 11;
7647       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
7648       orntNew[0] = 0;
7649       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
7650       orntNew[1] = -2;
7651       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
7652       orntNew[2] = -2;
7653       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
7654       orntNew[3] = 0;
7655       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7656       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7657 #if defined(PETSC_USE_DEBUG)
7658       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7659       for (p = 0; p < 4; ++p) {
7660         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7661       }
7662 #endif
7663       for (r = 0; r < 12; ++r) {
7664         newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + r;
7665         supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
7666         supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
7667         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
7668 #if defined(PETSC_USE_DEBUG)
7669         if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7670         for (p = 0; p < 2; ++p) {
7671           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
7672         }
7673 #endif
7674       }
7675     }
7676     /* Hybrid split faces have 4 edges and same cells */
7677     for (f = fMax; f < fEnd; ++f) {
7678       const PetscInt *cone, *ornt, *support;
7679       PetscInt        coneNew[4], orntNew[4];
7680       PetscInt        supportNew[2], size, s, c;
7681 
7682       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
7683       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
7684       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
7685       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
7686       for (r = 0; r < 2; ++r) {
7687         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + r;
7688 
7689         coneNew[0]   = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
7690         orntNew[0]   = ornt[0];
7691         coneNew[1]   = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
7692         orntNew[1]   = ornt[1];
7693         coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (cone[2+r] - eMax);
7694         orntNew[2+r] = 0;
7695         coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd      - eMax) + (f - fMax);
7696         orntNew[3-r] = 0;
7697         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7698         ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
7699 #if defined(PETSC_USE_DEBUG)
7700         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp, fMaxNew, fEndNew);
7701         for (p = 0; p < 2; ++p) {
7702           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7703         }
7704         for (p = 2; p < 4; ++p) {
7705           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", coneNew[p], eMaxNew, eEndNew);
7706         }
7707 #endif
7708         for (s = 0; s < size; ++s) {
7709           const PetscInt *coneCell, *orntCell, *fornt;
7710           PetscInt        o, of;
7711 
7712           ierr = DMPlexGetCone(dm, support[s], &coneCell);CHKERRQ(ierr);
7713           ierr = DMPlexGetConeOrientation(dm, support[s], &orntCell);CHKERRQ(ierr);
7714           o = orntCell[0] < 0 ? -1 : 1;
7715           for (c = 2; c < 6; ++c) if (coneCell[c] == f) break;
7716           if (c >= 6) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %D in cone of cell %D", f, support[s]);
7717           ierr = DMPlexGetConeOrientation(dm, coneCell[0], &fornt);CHKERRQ(ierr);
7718           of = fornt[c-2] < 0 ? -1 : 1;
7719           supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetQuadEdgeInverse_Static(orntCell[0], c-2) + (o*of < 0 ? 1-r : r))%4;
7720         }
7721         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
7722 #if defined(PETSC_USE_DEBUG)
7723         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp, fMaxNew, fEndNew);
7724         for (p = 0; p < size; ++p) {
7725           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", supportNew[p], cMaxNew, cEndNew);
7726         }
7727 #endif
7728       }
7729     }
7730     /* Hybrid cell faces have 4 edges and 2 cells */
7731     for (c = cMax; c < cEnd; ++c) {
7732       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4;
7733       const PetscInt *cone, *ornt;
7734       PetscInt        coneNew[4], orntNew[4];
7735       PetscInt        supportNew[2];
7736 
7737       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
7738       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
7739       for (r = 0; r < 4; ++r) {
7740 #if 0
7741         coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], r);
7742         orntNew[0] = 0;
7743         coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], r);
7744         orntNew[1] = 0;
7745         coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (cone[2+GetQuadEdge_Static(ornt[0], r)] - fMax);
7746         orntNew[2] = 0;
7747         coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd                                   - fMax) + (c - cMax);
7748         orntNew[3] = 0;
7749 #else
7750         coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + r;
7751         orntNew[0] = 0;
7752         coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + r;
7753         orntNew[1] = 0;
7754         coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (cone[2+r] - fMax);
7755         orntNew[2] = 0;
7756         coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd      - fMax) + (c - cMax);
7757         orntNew[3] = 0;
7758 #endif
7759         ierr = DMPlexSetCone(rdm, newp+r, coneNew);CHKERRQ(ierr);
7760         ierr = DMPlexSetConeOrientation(rdm, newp+r, orntNew);CHKERRQ(ierr);
7761 #if defined(PETSC_USE_DEBUG)
7762         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp+r, fMaxNew, fEndNew);
7763         for (p = 0; p < 2; ++p) {
7764           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7765         }
7766         for (p = 2; p < 4; ++p) {
7767           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", coneNew[p], eMaxNew, eEndNew);
7768         }
7769 #endif
7770         supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], r);
7771         supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], (r+1)%4);
7772         ierr          = DMPlexSetSupport(rdm, newp+r, supportNew);CHKERRQ(ierr);
7773 #if defined(PETSC_USE_DEBUG)
7774         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp+r, fMaxNew, fEndNew);
7775         for (p = 0; p < 2; ++p) {
7776           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", supportNew[p], cMaxNew, cEndNew);
7777         }
7778 #endif
7779       }
7780     }
7781     /* Interior split edges have 2 vertices and the same faces as the parent */
7782     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
7783     for (e = eStart; e < eMax; ++e) {
7784       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
7785 
7786       for (r = 0; r < 2; ++r) {
7787         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
7788         const PetscInt *cone, *ornt, *support;
7789         PetscInt        coneNew[2], coneSize, c, supportSize, s;
7790 
7791         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
7792         coneNew[0]       = vStartNew + (cone[0] - vStart);
7793         coneNew[1]       = vStartNew + (cone[1] - vStart);
7794         coneNew[(r+1)%2] = newv;
7795         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7796 #if defined(PETSC_USE_DEBUG)
7797         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
7798         for (p = 0; p < 2; ++p) {
7799           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
7800         }
7801 #endif
7802         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
7803         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
7804         for (s = 0; s < supportSize; ++s) {
7805           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
7806           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
7807           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
7808           for (c = 0; c < coneSize; ++c) {
7809             if (cone[c] == e) break;
7810           }
7811           if (support[s] < fMax) {
7812             supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%4;
7813           } else {
7814             supportRef[s] = fStartNew + (fMax       - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
7815           }
7816         }
7817         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
7818 #if defined(PETSC_USE_DEBUG)
7819         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
7820         for (p = 0; p < supportSize; ++p) {
7821           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
7822         }
7823 #endif
7824       }
7825     }
7826     /* Interior face edges have 2 vertices and 2+cells faces */
7827     for (f = fStart; f < fMax; ++f) {
7828       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};
7829       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
7830       const PetscInt *cone, *coneCell, *orntCell, *support;
7831       PetscInt        coneNew[2], coneSize, c, supportSize, s;
7832 
7833       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
7834       for (r = 0; r < 4; ++r) {
7835         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
7836 
7837         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
7838         coneNew[1] = newv;
7839         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7840 #if defined(PETSC_USE_DEBUG)
7841         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
7842         for (p = 0; p < 2; ++p) {
7843           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
7844         }
7845 #endif
7846         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
7847         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
7848         supportRef[0] = fStartNew + (f - fStart)*4 + r;
7849         supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
7850         for (s = 0; s < supportSize; ++s) {
7851           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
7852           ierr = DMPlexGetCone(dm, support[s], &coneCell);CHKERRQ(ierr);
7853           ierr = DMPlexGetConeOrientation(dm, support[s], &orntCell);CHKERRQ(ierr);
7854           for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
7855           if (support[s] < cMax) {
7856             supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
7857           } else {
7858             supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + r;
7859           }
7860         }
7861         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
7862 #if defined(PETSC_USE_DEBUG)
7863         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
7864         for (p = 0; p < 2+supportSize; ++p) {
7865           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
7866         }
7867 #endif
7868       }
7869     }
7870     /* Interior cell edges have 2 vertices and 4 faces */
7871     for (c = cStart; c < cMax; ++c) {
7872       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};
7873       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
7874       const PetscInt *cone;
7875       PetscInt        coneNew[2], supportNew[4];
7876 
7877       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
7878       for (r = 0; r < 6; ++r) {
7879         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
7880 
7881         coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[r] - fStart);
7882         coneNew[1] = newv;
7883         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7884 #if defined(PETSC_USE_DEBUG)
7885         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
7886         for (p = 0; p < 2; ++p) {
7887           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
7888         }
7889 #endif
7890         for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
7891         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
7892 #if defined(PETSC_USE_DEBUG)
7893         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
7894         for (p = 0; p < 4; ++p) {
7895           if ((supportNew[p] < fStartNew) || (supportNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fMaxNew);
7896         }
7897 #endif
7898       }
7899     }
7900     /* Hybrid edges have two vertices and the same faces */
7901     for (e = eMax; e < eEnd; ++e) {
7902       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (e - eMax);
7903       const PetscInt *cone, *support, *fcone;
7904       PetscInt        coneNew[2], size, fsize, s;
7905 
7906       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
7907       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
7908       ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
7909       coneNew[0] = vStartNew + (cone[0] - vStart);
7910       coneNew[1] = vStartNew + (cone[1] - vStart);
7911       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7912 #if defined(PETSC_USE_DEBUG)
7913       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
7914       for (p = 0; p < 2; ++p) {
7915         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
7916       }
7917 #endif
7918       for (s = 0; s < size; ++s) {
7919         ierr = DMPlexGetConeSize(dm, support[s], &fsize);CHKERRQ(ierr);
7920         ierr = DMPlexGetCone(dm, support[s], &fcone);CHKERRQ(ierr);
7921         for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
7922         if ((c < 2) || (c > 3)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Edge %D not found in cone of face %D", e, support[s]);
7923         supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + c-2;
7924       }
7925       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
7926 #if defined(PETSC_USE_DEBUG)
7927       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
7928       for (p = 0; p < size; ++p) {
7929         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", supportRef[p], fMaxNew, fEndNew);
7930       }
7931 #endif
7932     }
7933     /* Hybrid face edges have 2 vertices and 2+cells faces */
7934     for (f = fMax; f < fEnd; ++f) {
7935       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
7936       const PetscInt *cone, *support, *ccone, *cornt;
7937       PetscInt        coneNew[2], size, csize, s;
7938 
7939       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
7940       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
7941       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
7942       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
7943       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
7944       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7945 #if defined(PETSC_USE_DEBUG)
7946       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
7947       for (p = 0; p < 2; ++p) {
7948         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
7949       }
7950 #endif
7951       supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 0;
7952       supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 1;
7953       for (s = 0; s < size; ++s) {
7954         ierr = DMPlexGetConeSize(dm, support[s], &csize);CHKERRQ(ierr);
7955         ierr = DMPlexGetCone(dm, support[s], &ccone);CHKERRQ(ierr);
7956         ierr = DMPlexGetConeOrientation(dm, support[s], &cornt);CHKERRQ(ierr);
7957         for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
7958         if ((c < 2) || (c >= csize)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Hybrid face %D is not in cone of hybrid cell %D", f, support[s]);
7959         supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + c-2;
7960       }
7961       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
7962 #if defined(PETSC_USE_DEBUG)
7963       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
7964       for (p = 0; p < 2+size; ++p) {
7965         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", supportRef[p], fMaxNew, fEndNew);
7966       }
7967 #endif
7968     }
7969     /* Hybrid cell edges have 2 vertices and 4 faces */
7970     for (c = cMax; c < cEnd; ++c) {
7971       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
7972       const PetscInt *cone, *support;
7973       PetscInt        coneNew[2], size;
7974 
7975       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
7976       ierr = DMPlexGetSupportSize(dm, c, &size);CHKERRQ(ierr);
7977       ierr = DMPlexGetSupport(dm, c, &support);CHKERRQ(ierr);
7978       coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[0] - fStart);
7979       coneNew[1] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[1] - fStart);
7980       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
7981 #if defined(PETSC_USE_DEBUG)
7982       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
7983       for (p = 0; p < 2; ++p) {
7984         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
7985       }
7986 #endif
7987       supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 0;
7988       supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 1;
7989       supportRef[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 2;
7990       supportRef[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 3;
7991       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
7992 #if defined(PETSC_USE_DEBUG)
7993       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
7994       for (p = 0; p < 4; ++p) {
7995         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", supportRef[p], fMaxNew, fEndNew);
7996       }
7997 #endif
7998     }
7999     /* Interior vertices have identical supports */
8000     for (v = vStart; v < vEnd; ++v) {
8001       const PetscInt  newp = vStartNew + (v - vStart);
8002       const PetscInt *support, *cone;
8003       PetscInt        size, s;
8004 
8005       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
8006       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
8007       for (s = 0; s < size; ++s) {
8008         PetscInt r = 0;
8009 
8010         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
8011         if (cone[1] == v) r = 1;
8012         if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
8013         else                   supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (support[s] - eMax);
8014       }
8015       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
8016 #if defined(PETSC_USE_DEBUG)
8017       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
8018       for (p = 0; p < size; ++p) {
8019         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
8020       }
8021 #endif
8022     }
8023     /* Interior edge vertices have 2 + faces supports */
8024     for (e = eStart; e < eMax; ++e) {
8025       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
8026       const PetscInt *cone, *support;
8027       PetscInt        size, s;
8028 
8029       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
8030       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
8031       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
8032       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
8033       for (s = 0; s < size; ++s) {
8034         PetscInt r;
8035 
8036         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
8037         for (r = 0; r < 4; ++r) if (cone[r] == e) break;
8038         if (support[s] < fMax) {
8039           supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*4 + r;
8040         } else {
8041           supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (fMax       - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (support[s] - fMax);
8042         }
8043       }
8044       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
8045 #if defined(PETSC_USE_DEBUG)
8046       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
8047       for (p = 0; p < 2+size; ++p) {
8048         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
8049       }
8050 #endif
8051     }
8052     /* Interior face vertices have 4 + cells supports */
8053     for (f = fStart; f < fMax; ++f) {
8054       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
8055       const PetscInt *cone, *support;
8056       PetscInt        size, s;
8057 
8058       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
8059       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
8060       for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eMax - eStart)*2 +  (f - fStart)*4 + r;
8061       for (s = 0; s < size; ++s) {
8062         PetscInt r;
8063 
8064         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
8065         for (r = 0; r < 6; ++r) if (cone[r] == f) break;
8066         if (support[s] < cMax) {
8067           supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (support[s] - cStart)*6 + r;
8068         } else {
8069           supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax       - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (support[s] - cMax);
8070         }
8071       }
8072       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
8073 #if defined(PETSC_USE_DEBUG)
8074       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
8075       for (p = 0; p < 4+size; ++p) {
8076         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
8077       }
8078 #endif
8079     }
8080     /* Cell vertices have 6 supports */
8081     for (c = cStart; c < cMax; ++c) {
8082       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
8083       PetscInt       supportNew[6];
8084 
8085       for (r = 0; r < 6; ++r) {
8086         supportNew[r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
8087       }
8088       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
8089     }
8090     ierr = PetscFree(supportRef);CHKERRQ(ierr);
8091     break;
8092   default:
8093     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
8094   }
8095   PetscFunctionReturn(0);
8096 }
8097 
8098 static PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
8099 {
8100   PetscSection          coordSection, coordSectionNew;
8101   Vec                   coordinates, coordinatesNew;
8102   PetscScalar          *coords, *coordsNew;
8103   const PetscInt        numVertices = depthSize ? depthSize[0] : 0;
8104   PetscInt              dim, spaceDim, depth, bs, coordSizeNew, cStart, cEnd, cMax;
8105   PetscInt              c, vStart, vStartNew, vEnd, v, eStart, eEnd, eMax, e, fStart, fEnd, fMax, f;
8106   PetscInt              cStartNew, cEndNew, vEndNew, *parentId = NULL;
8107   VecType               vtype;
8108   PetscBool             isperiodic, localize = PETSC_FALSE, needcoords = PETSC_FALSE;
8109   const PetscReal      *maxCell, *L;
8110   const DMBoundaryType *bd;
8111   PetscErrorCode        ierr;
8112 
8113   PetscFunctionBegin;
8114   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
8115   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
8116   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
8117   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
8118   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
8119   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
8120   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, NULL);CHKERRQ(ierr);
8121   if (cMax < 0) cMax = cEnd;
8122   if (fMax < 0) fMax = fEnd;
8123   if (eMax < 0) eMax = eEnd;
8124   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, NULL, NULL, &vStartNew);CHKERRQ(ierr);
8125   ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, NULL, NULL, &vEndNew);CHKERRQ(ierr);
8126   ierr = DMGetPeriodicity(dm, &isperiodic, &maxCell, &L, &bd);CHKERRQ(ierr);
8127   /* Determine if we need to localize coordinates when generating them */
8128   if (isperiodic && !maxCell) {
8129     ierr = DMGetCoordinatesLocalized(dm, &localize);CHKERRQ(ierr);
8130     if (!localize) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot refine if coordinates have not been localized");
8131   }
8132   if (isperiodic) {
8133     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)dm),((PetscObject)dm)->prefix,"DMPlex coords refinement options","DM");CHKERRQ(ierr);
8134     ierr = PetscOptionsBool("-dm_plex_refine_localize","Automatically localize from parent cells",NULL,localize,&localize,NULL);CHKERRQ(ierr);
8135     ierr = PetscOptionsEnd();CHKERRQ(ierr);
8136     if (localize) {
8137       ierr = DMLocalizeCoordinates(dm);CHKERRQ(ierr);
8138     }
8139   }
8140   ierr = DMSetPeriodicity(rdm, isperiodic,  maxCell,  L,  bd);CHKERRQ(ierr);
8141 
8142   ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
8143   ierr = PetscSectionGetFieldComponents(coordSection, 0, &spaceDim);CHKERRQ(ierr);
8144   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr);
8145   ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr);
8146   ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, spaceDim);CHKERRQ(ierr);
8147 
8148   if (localize) {
8149     PetscInt p, r, newp, *pi;
8150 
8151     /* New coordinates will be already localized on the cell */
8152     ierr = PetscSectionSetChart(coordSectionNew, 0, vStartNew+numVertices);CHKERRQ(ierr);
8153 
8154     /* We need the parentId to properly localize coordinates */
8155     ierr = PetscMalloc1(cEndNew-cStartNew,&pi);CHKERRQ(ierr);
8156     switch (refiner) {
8157     case REFINER_NOOP:
8158       break;
8159     case REFINER_SIMPLEX_1D:
8160       for (p = cStart; p < cEnd; ++p) {
8161         for (r = 0; r < 2; ++r) {
8162           newp     = (p - cStart)*2 + r;
8163           pi[newp] = p;
8164         }
8165       }
8166       break;
8167     case REFINER_SIMPLEX_2D:
8168       for (p = cStart; p < cEnd; ++p) {
8169         for (r = 0; r < 4; ++r) {
8170           newp     = (p - cStart)*4 + r;
8171           pi[newp] = p;
8172         }
8173       }
8174       break;
8175     case REFINER_HEX_2D:
8176       for (p = cStart; p < cEnd; ++p) {
8177         for (r = 0; r < 4; ++r) {
8178           newp     = (p - cStart)*4 + r;
8179           pi[newp] = p;
8180         }
8181       }
8182       break;
8183     case REFINER_SIMPLEX_TO_HEX_2D:
8184       for (p = cStart; p < cEnd; ++p) {
8185         for (r = 0; r < 3; ++r) {
8186           newp     = (p - cStart)*3 + r;
8187           pi[newp] = p;
8188         }
8189       }
8190       break;
8191     case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
8192       for (p = cStart; p < cMax; ++p) {
8193         for (r = 0; r < 3; ++r) {
8194           newp     = (p - cStart)*3 + r;
8195           pi[newp] = p;
8196         }
8197       }
8198       for (p = cMax; p < cEnd; ++p) {
8199         for (r = 0; r < 4; ++r) {
8200           newp     = (cMax - cStart)*3 + (p - cMax)*4 + r;
8201           pi[newp] = p;
8202         }
8203       }
8204       /* The refiner needs midpoint vertices on hybrid edges and hybrid cells */
8205       cMax = cEnd;
8206       eMax = eEnd;
8207       break;
8208     case REFINER_HYBRID_SIMPLEX_2D:
8209       for (p = cStart; p < cMax; ++p) {
8210         for (r = 0; r < 4; ++r) {
8211           newp     = (p - cStart)*4 + r;
8212           pi[newp] = p;
8213         }
8214       }
8215       for (p = cMax; p < cEnd; ++p) {
8216         for (r = 0; r < 2; ++r) {
8217           newp     = (cMax - cStart)*4 + (p - cMax)*2 + r;
8218           pi[newp] = p;
8219         }
8220       }
8221       break;
8222     case REFINER_HYBRID_HEX_2D:
8223       for (p = cStart; p < cMax; ++p) {
8224         for (r = 0; r < 4; ++r) {
8225           newp     = (p - cStart)*4 + r;
8226           pi[newp] = p;
8227         }
8228       }
8229       for (p = cMax; p < cEnd; ++p) {
8230         for (r = 0; r < 2; ++r) {
8231           newp     = (cMax - cStart)*4 + (p - cMax)*2 + r;
8232           pi[newp] = p;
8233         }
8234       }
8235       break;
8236     case REFINER_SIMPLEX_3D:
8237       for (p = cStart; p < cEnd; ++p) {
8238         for (r = 0; r < 8; ++r) {
8239           newp     = (p - cStart)*8 + r;
8240           pi[newp] = p;
8241         }
8242       }
8243       break;
8244     case REFINER_HYBRID_SIMPLEX_3D:
8245       for (p = cStart; p < cMax; ++p) {
8246         for (r = 0; r < 8; ++r) {
8247           newp     = (p - cStart)*8 + r;
8248           pi[newp] = p;
8249         }
8250       }
8251       for (p = cMax; p < cEnd; ++p) {
8252         for (r = 0; r < 4; ++r) {
8253           newp     = (cMax - cStart)*8 + (p - cMax)*4 + r;
8254           pi[newp] = p;
8255         }
8256       }
8257       break;
8258     case REFINER_SIMPLEX_TO_HEX_3D:
8259       for (p = cStart; p < cEnd; ++p) {
8260         for (r = 0; r < 4; ++r) {
8261           newp     = (p - cStart)*4 + r;
8262           pi[newp] = p;
8263         }
8264       }
8265       break;
8266     case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
8267       for (p = cStart; p < cMax; ++p) {
8268         for (r = 0; r < 4; ++r) {
8269           newp     = (p - cStart)*4 + r;
8270           pi[newp] = p;
8271         }
8272       }
8273       for (p = cMax; p < cEnd; ++p) {
8274         for (r = 0; r < 3; ++r) {
8275           newp     = (cMax - cStart)*4 + (p - cMax)*3 + r;
8276           pi[newp] = p;
8277         }
8278       }
8279       break;
8280     case REFINER_HEX_3D:
8281       for (p = cStart; p < cEnd; ++p) {
8282         for (r = 0; r < 8; ++r) {
8283           newp = (p - cStart)*8 + r;
8284           pi[newp] = p;
8285         }
8286       }
8287       break;
8288     case REFINER_HYBRID_HEX_3D:
8289       for (p = cStart; p < cMax; ++p) {
8290         for (r = 0; r < 8; ++r) {
8291           newp = (p - cStart)*8 + r;
8292           pi[newp] = p;
8293         }
8294       }
8295       for (p = cMax; p < cEnd; ++p) {
8296         for (r = 0; r < 4; ++r) {
8297           newp = (cMax - cStart)*8 + (p - cMax)*4 + r;
8298           pi[newp] = p;
8299         }
8300       }
8301       break;
8302     default:
8303       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
8304     }
8305     parentId = pi;
8306   } else {
8307     /* The refiner needs midpoint vertices on hybrid edges and hybrid cells */
8308     if (REFINER_HYBRID_SIMPLEX_TO_HEX_2D == refiner) { cMax = cEnd; eMax = eEnd; }
8309     ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+numVertices);CHKERRQ(ierr);
8310   }
8311 
8312   /* All vertices have the spaceDim coordinates */
8313   if (localize) {
8314     PetscInt c;
8315 
8316     for (c = cStartNew; c < cEndNew; ++c) {
8317       PetscInt *cone = NULL;
8318       PetscInt  closureSize, coneSize = 0, p, pdof;
8319 
8320       ierr = PetscSectionGetDof(coordSection, parentId[c], &pdof); CHKERRQ(ierr);
8321       if (pdof) { /* localize on all cells that are refinement of a localized parent cell */
8322         ierr = DMPlexGetTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
8323         for (p = 0; p < closureSize*2; p += 2) {
8324           const PetscInt point = cone[p];
8325           if ((point >= vStartNew) && (point < vEndNew)) coneSize++;
8326         }
8327         ierr = DMPlexRestoreTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
8328         ierr = PetscSectionSetDof(coordSectionNew, c, coneSize*spaceDim);CHKERRQ(ierr);
8329         ierr = PetscSectionSetFieldDof(coordSectionNew, c, 0, coneSize*spaceDim);CHKERRQ(ierr);
8330       }
8331     }
8332   }
8333   for (v = vStartNew; v < vStartNew+numVertices; ++v) {
8334     ierr = PetscSectionSetDof(coordSectionNew, v, spaceDim);CHKERRQ(ierr);
8335     ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, spaceDim);CHKERRQ(ierr);
8336   }
8337   ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr);
8338   ierr = DMSetCoordinateSection(rdm, PETSC_DETERMINE, coordSectionNew);CHKERRQ(ierr);
8339   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
8340   ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr);
8341   ierr = VecCreate(PETSC_COMM_SELF, &coordinatesNew);CHKERRQ(ierr);
8342   ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr);
8343   ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr);
8344   ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr);
8345   ierr = VecSetBlockSize(coordinatesNew, bs);CHKERRQ(ierr);
8346   ierr = VecGetType(coordinates, &vtype);CHKERRQ(ierr);
8347   ierr = VecSetType(coordinatesNew, vtype);CHKERRQ(ierr);
8348   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
8349   ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
8350 
8351   switch (refiner) {
8352   case REFINER_NOOP: break;
8353   case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
8354   case REFINER_SIMPLEX_TO_HEX_3D:
8355   case REFINER_HEX_3D:
8356   case REFINER_HYBRID_HEX_3D:
8357     /* Face vertices have the average of corner coordinates */
8358     for (f = fStart; f < fMax; ++f) {
8359       const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
8360       PetscInt      *cone = NULL;
8361       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;
8362 
8363       ierr = DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
8364       for (p = 0; p < closureSize*2; p += 2) {
8365         const PetscInt point = cone[p];
8366         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
8367       }
8368       if (localize) {
8369         const PetscInt *support = NULL;
8370         PetscInt       *rStar = NULL;
8371         PetscInt        supportSize, rStarSize, coff, s, ccoff[8];
8372         PetscBool       cellfound = PETSC_FALSE;
8373 
8374         ierr = DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);CHKERRQ(ierr);
8375         ierr = DMPlexGetSupportSize(dm,f,&supportSize);CHKERRQ(ierr);
8376         ierr = DMPlexGetSupport(dm,f,&support);CHKERRQ(ierr);
8377         /* Compute average of coordinates for each cell sharing the face */
8378         for (s = 0; s < supportSize; ++s) {
8379           PetscScalar     coordsNewAux[3] = { 0.0, 0.0, 0.0 };
8380           PetscInt       *cellCone = NULL;
8381           PetscInt        cellClosureSize, cellConeSize = 0, cdof;
8382           const PetscInt  cell = support[s];
8383           PetscBool       copyoff = PETSC_FALSE;
8384 
8385           ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);CHKERRQ(ierr);
8386           for (p = 0; p < cellClosureSize*2; p += 2) {
8387             const PetscInt point = cellCone[p];
8388             if ((point >= vStart) && (point < vEnd)) cellCone[cellConeSize++] = point;
8389           }
8390           ierr = PetscSectionGetDof(coordSection, cell, &cdof);CHKERRQ(ierr);
8391           if (!cdof) { /* the parent cell does not have localized coordinates */
8392             cellfound = PETSC_TRUE;
8393             for (v = 0; v < coneSize; ++v) {
8394               ierr = PetscSectionGetOffset(coordSection, cone[v], &off[v]);CHKERRQ(ierr);
8395               for (d = 0; d < spaceDim; ++d) coordsNewAux[d] += coords[off[v]+d];
8396             }
8397             for (d = 0; d < spaceDim; ++d) coordsNewAux[d] /= coneSize;
8398           } else {
8399             ierr = PetscSectionGetOffset(coordSection, cell, &coff);CHKERRQ(ierr);
8400             for (p = 0; p < coneSize; ++p) {
8401               const PetscInt tv = cone[p];
8402               PetscInt       cv, voff;
8403               PetscBool      locv = PETSC_TRUE;
8404 
8405               for (cv = 0; cv < cellConeSize; ++cv) {
8406                 if (cellCone[cv] == tv) {
8407                   ccoff[p] = spaceDim*cv + coff;
8408                   break;
8409                 }
8410               }
8411               if (cv == cellConeSize) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map vertex %D",tv);
8412 
8413               ierr = PetscSectionGetOffset(coordSection, cone[p], &voff);CHKERRQ(ierr);
8414               for (d = 0; d < spaceDim; ++d) {
8415                 coordsNewAux[d] += coords[ccoff[p]+d];
8416                 if (!cellfound && coords[voff+d] != coords[ccoff[p]+d]) locv = PETSC_FALSE;
8417               }
8418               if (locv && !cellfound) {
8419                 cellfound = PETSC_TRUE;
8420                 copyoff   = PETSC_TRUE;
8421               }
8422             }
8423             for (d = 0; d < spaceDim; ++d) coordsNewAux[d] /= coneSize;
8424 
8425             /* Found a valid face for the "vertex" part of the Section (physical space)
8426                i.e., a face that has at least one corner in the physical space */
8427             if (copyoff) for (p = 0; p < coneSize; ++p) off[p] = ccoff[p];
8428           }
8429 
8430           /* Localize new coordinates on each refined cell */
8431           for (v = 0; v < rStarSize*2; v += 2) {
8432             if ((rStar[v] >= cStartNew) && (rStar[v] < cEndNew) && parentId[rStar[v]-cStartNew] == cell) {
8433               PetscInt       *rcone = NULL, rclosureSize, lid, rcdof, rcoff;
8434               const PetscInt  rcell = rStar[v];
8435 
8436               ierr = PetscSectionGetDof(coordSectionNew, rcell, &rcdof);CHKERRQ(ierr);
8437               if (!rcdof) continue;
8438               ierr = PetscSectionGetOffset(coordSectionNew, rcell, &rcoff);CHKERRQ(ierr);
8439               ierr = DMPlexGetTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);CHKERRQ(ierr);
8440               for (p = 0, lid = 0; p < rclosureSize*2; p += 2) {
8441                 if (rcone[p] == newv) {
8442                   for (d = 0; d < spaceDim; d++) coordsNew[rcoff + lid*spaceDim + d] = coordsNewAux[d];
8443                   break;
8444                 }
8445                 if (rcone[p] >= vStartNew && rcone[p] < vEndNew) lid++;
8446               }
8447               ierr = DMPlexRestoreTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);CHKERRQ(ierr);
8448               if (p == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D",newv);
8449             }
8450           }
8451           ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);CHKERRQ(ierr);
8452         }
8453         ierr = DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);CHKERRQ(ierr);
8454         if (!cellfound) {
8455           /* Could not find a valid face for the vertex part, we will get this vertex later (final reduction) */
8456           needcoords = PETSC_TRUE;
8457           coneSize   = 0;
8458         }
8459       } else {
8460         for (v = 0; v < coneSize; ++v) {
8461           ierr = PetscSectionGetOffset(coordSection, cone[v], &off[v]);CHKERRQ(ierr);
8462         }
8463       }
8464       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
8465       if (coneSize) {
8466         for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = 0.0;
8467         for (v = 0; v < coneSize; ++v) {ierr = DMLocalizeAddCoordinate_Internal(dm, spaceDim, &coords[off[0]], &coords[off[v]], &coordsNew[offnew]);CHKERRQ(ierr);}
8468         for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] /= coneSize;
8469       } else {
8470         for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = PETSC_MIN_REAL;
8471       }
8472       ierr = DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
8473     }
8474   case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
8475   case REFINER_SIMPLEX_TO_HEX_2D:
8476   case REFINER_HEX_2D:
8477   case REFINER_HYBRID_HEX_2D:
8478   case REFINER_SIMPLEX_1D:
8479     /* Cell vertices have the average of corner coordinates */
8480     for (c = cStart; c < cMax; ++c) {
8481       const PetscInt newv = vStartNew + (vEnd - vStart) + (dim > 1 ? (eMax - eStart) : 0) + (c - cStart) + (dim > 2 ? (fMax - fStart) : 0);
8482       PetscInt      *cone = NULL;
8483       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d, cdof = 0;
8484 
8485       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
8486       for (p = 0; p < closureSize*2; p += 2) {
8487         const PetscInt point = cone[p];
8488         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
8489       }
8490       if (localize) {
8491         ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr);
8492       }
8493       if (cdof) {
8494         PetscInt coff;
8495 
8496         ierr = PetscSectionGetOffset(coordSection, c, &coff);CHKERRQ(ierr);
8497         for (v = 0; v < coneSize; ++v) off[v] = spaceDim*v + coff;
8498       } else {
8499         for (v = 0; v < coneSize; ++v) {
8500           ierr = PetscSectionGetOffset(coordSection, cone[v], &off[v]);CHKERRQ(ierr);
8501         }
8502       }
8503       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
8504       for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = 0.0;
8505       for (v = 0; v < coneSize; ++v) {ierr = DMLocalizeAddCoordinate_Internal(dm, spaceDim, &coords[off[0]], &coords[off[v]], &coordsNew[offnew]);CHKERRQ(ierr);}
8506       for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] /= coneSize;
8507       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
8508 
8509       /* Localize new coordinates on each refined cell */
8510       if (cdof) {
8511         PetscInt *rStar = NULL, rStarSize;
8512 
8513         ierr = DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);CHKERRQ(ierr);
8514         for (v = 0; v < rStarSize*2; v += 2) {
8515           if ((rStar[v] >= cStartNew) && (rStar[v] < cEndNew)) {
8516             PetscInt *cone = NULL, closureSize, lid, coff, rc, rcdof;
8517 
8518             rc   = rStar[v];
8519             ierr = PetscSectionGetDof(coordSectionNew, rc, &rcdof);CHKERRQ(ierr);
8520             if (!rcdof) continue;
8521             ierr = PetscSectionGetOffset(coordSectionNew, rc, &coff);CHKERRQ(ierr);
8522             ierr = DMPlexGetTransitiveClosure(rdm, rc, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
8523             for (p = 0, lid = 0; p < closureSize*2; p += 2) {
8524               if (cone[p] == newv) {
8525                 for (d = 0; d < spaceDim; d++) coordsNew[coff + lid*spaceDim + d] = coordsNew[offnew + d];
8526                 break;
8527               }
8528               if (cone[p] >= vStartNew && cone[p] < vEndNew) lid++;
8529             }
8530             if (p == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D",newv);
8531             ierr = DMPlexRestoreTransitiveClosure(rdm, rc, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
8532           }
8533         }
8534         ierr = DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);CHKERRQ(ierr);
8535       }
8536     }
8537   case REFINER_SIMPLEX_2D:
8538   case REFINER_HYBRID_SIMPLEX_2D:
8539   case REFINER_SIMPLEX_3D:
8540   case REFINER_HYBRID_SIMPLEX_3D:
8541     /* Edge vertices have the average of endpoint coordinates */
8542     for (e = eStart; e < eMax; ++e) {
8543       const PetscInt  newv = vStartNew + (vEnd - vStart) + (e - eStart);
8544       const PetscInt *cone;
8545       PetscInt        coneSize, offA, offB, offnew, d;
8546 
8547       ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr);
8548       if (coneSize != 2) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize);
8549       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
8550       if (localize) {
8551         PetscInt   coff, toffA = -1, toffB = -1, voffA, voffB;
8552         PetscInt  *eStar = NULL, eStarSize;
8553         PetscInt  *rStar = NULL, rStarSize;
8554         PetscBool  cellfound = PETSC_FALSE;
8555 
8556         offA = offB = -1;
8557         ierr = PetscSectionGetOffset(coordSection, cone[0], &voffA);CHKERRQ(ierr);
8558         ierr = PetscSectionGetOffset(coordSection, cone[1], &voffB);CHKERRQ(ierr);
8559         ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &eStarSize, &eStar);CHKERRQ(ierr);
8560         ierr = DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);CHKERRQ(ierr);
8561         for (v = 0; v < eStarSize*2; v += 2) {
8562           if ((eStar[v] >= cStart) && (eStar[v] < cEnd)) {
8563             PetscScalar     coordsNewAux[3];
8564             PetscInt       *cellCone = NULL;
8565             PetscInt        cellClosureSize, s, cv, cdof;
8566             PetscBool       locvA = PETSC_TRUE, locvB = PETSC_TRUE;
8567             const PetscInt  cell = eStar[v];
8568 
8569             ierr = PetscSectionGetDof(coordSection, cell, &cdof);CHKERRQ(ierr);
8570             if (!cdof) {
8571               /* Found a valid edge for the "vertex" part of the Section */
8572               offA = voffA;
8573               offB = voffB;
8574               cellfound = PETSC_TRUE;
8575             } else {
8576               ierr = PetscSectionGetOffset(coordSection, cell, &coff);CHKERRQ(ierr);
8577               ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);CHKERRQ(ierr);
8578               for (s = 0, cv = 0; s < cellClosureSize*2; s += 2) {
8579                 const PetscInt point = cellCone[s];
8580                 if ((point >= vStart) && (point < vEnd)) {
8581                   if (point == cone[0]) toffA = spaceDim*cv + coff;
8582                   else if (point == cone[1]) toffB = spaceDim*cv + coff;
8583                   cv++;
8584                 }
8585               }
8586               ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);CHKERRQ(ierr);
8587               for (d = 0; d < spaceDim; ++d) {
8588                 coordsNewAux[d] = 0.5*(coords[toffA+d] + coords[toffB+d]);
8589                 if (coords[toffA+d] != coords[voffA+d]) locvA = PETSC_FALSE;
8590                 if (coords[toffB+d] != coords[voffB+d]) locvB = PETSC_FALSE;
8591               }
8592               /* Found a valid edge for the "vertex" part of the Section */
8593               if (!cellfound && (locvA || locvB)) {
8594                 cellfound = PETSC_TRUE;
8595                 offA = toffA;
8596                 offB = toffB;
8597               }
8598             }
8599 
8600             /* Localize new coordinates on each refined cell */
8601             for (s = 0; s < rStarSize*2; s += 2) {
8602               if ((rStar[s] >= cStartNew) && (rStar[s] < cEndNew) && parentId[rStar[s]-cStartNew] == cell) {
8603                 PetscInt       *rcone = NULL, rclosureSize, lid, p, rcdof;
8604                 const PetscInt  rcell = rStar[s];
8605 
8606                 ierr = PetscSectionGetDof(coordSectionNew, rcell, &rcdof);CHKERRQ(ierr);
8607                 if (!rcdof) continue;
8608                 ierr = PetscSectionGetOffset(coordSectionNew, rcell, &coff);CHKERRQ(ierr);
8609                 ierr = DMPlexGetTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);CHKERRQ(ierr);
8610                 for (p = 0, lid = 0; p < rclosureSize*2; p += 2) {
8611                   if (rcone[p] == newv) {
8612                     for (d = 0; d < spaceDim; d++) coordsNew[coff + lid*spaceDim + d] = coordsNewAux[d];
8613                     break;
8614                   }
8615                   if (rcone[p] >= vStartNew && rcone[p] < vEndNew) lid++;
8616                 }
8617                 ierr = DMPlexRestoreTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);CHKERRQ(ierr);
8618                 if (p == rclosureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D",newv);
8619               }
8620             }
8621           }
8622         }
8623         ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &eStarSize, &eStar);CHKERRQ(ierr);
8624         ierr = DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);CHKERRQ(ierr);
8625         if (!cellfound) {
8626           /* Could not find a valid edge for the vertex part, we will get this vertex later (final reduction) */
8627           needcoords = PETSC_TRUE;
8628         }
8629       } else {
8630         ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
8631         ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
8632       }
8633       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
8634       if (offA != -1 && offB != -1) {
8635         ierr = DMLocalizeCoordinate_Internal(dm, spaceDim, &coords[offA], &coords[offB], &coordsNew[offnew]);CHKERRQ(ierr);
8636         for (d = 0; d < spaceDim; ++d) {
8637           coordsNew[offnew+d] = 0.5*(coords[offA+d] + coordsNew[offnew+d]);
8638         }
8639       } else {
8640         for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = PETSC_MIN_REAL;
8641       }
8642     }
8643     /* Old vertices have the same coordinates */
8644     for (v = vStart; v < vEnd; ++v) {
8645       const PetscInt newv = vStartNew + (v - vStart);
8646       PetscInt       off, offnew, d;
8647 
8648       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
8649       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
8650       for (d = 0; d < spaceDim; ++d) {
8651         coordsNew[offnew+d] = coords[off+d];
8652       }
8653 
8654       /* Localize new coordinates on each refined cell */
8655       if (localize) {
8656         PetscInt  p;
8657         PetscInt *rStar = NULL, rStarSize;
8658 
8659         ierr = DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);CHKERRQ(ierr);
8660         for (p = 0; p < rStarSize*2; p += 2) {
8661           if ((rStar[p] >= cStartNew) && (rStar[p] < cEndNew)) {
8662             PetscScalar  ocoords[3];
8663             PetscInt    *cone = NULL, closureSize, lid, coff, s, oc, cdof;
8664 
8665             c    = rStar[p];
8666             oc   = parentId[c-cStartNew];
8667             ierr = PetscSectionGetDof(coordSectionNew, c, &cdof);CHKERRQ(ierr);
8668             if (!cdof) continue;
8669             ierr = PetscSectionGetDof(coordSection, oc, &cdof);CHKERRQ(ierr);
8670             if (!cdof) continue;
8671             ierr = PetscSectionGetOffset(coordSection, oc, &coff);CHKERRQ(ierr);
8672             ierr = DMPlexGetTransitiveClosure(dm, oc, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
8673             for (s = 0, lid = 0; s < closureSize*2; s += 2) {
8674               if (cone[s] == v) {
8675                 for (d = 0; d < spaceDim; d++) ocoords[d] = coords[coff + lid*spaceDim + d];
8676                 break;
8677               }
8678               if (cone[s] >= vStart && cone[s] < vEnd) lid++;
8679             }
8680             if (s == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map old vertex %D",v);
8681             ierr = DMPlexRestoreTransitiveClosure(dm, oc, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
8682 
8683             ierr = PetscSectionGetOffset(coordSectionNew, c, &coff);CHKERRQ(ierr);
8684             ierr = DMPlexGetTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
8685             for (s = 0, lid = 0; s < closureSize*2; s += 2) {
8686               if (cone[s] == newv) {
8687                 for (d = 0; d < spaceDim; d++) coordsNew[coff + lid*spaceDim + d] = ocoords[d];
8688                 break;
8689               }
8690               if (cone[s] >= vStartNew && cone[s] < vEndNew) lid++;
8691             }
8692             if (s == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D",newv);
8693             ierr = DMPlexRestoreTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
8694           }
8695         }
8696         ierr = DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);CHKERRQ(ierr);
8697       }
8698     }
8699     break;
8700   default:
8701     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
8702   }
8703   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
8704   ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
8705   ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr);
8706 
8707   /* Final reduction (if needed) if we are localizing */
8708   if (localize) {
8709     PetscBool gred;
8710 
8711     ierr = MPIU_Allreduce(&needcoords, &gred, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)rdm));CHKERRQ(ierr);
8712     if (gred) {
8713       DM                 cdm;
8714       Vec                aux;
8715       PetscSF            sf;
8716       const PetscScalar *lArray;
8717       PetscScalar       *gArray;
8718 #if defined(PETSC_USE_COMPLEX)
8719       PetscInt          i, ln, gn;
8720       PetscReal         *lrArray;
8721       PetscReal         *grArray;
8722 #endif
8723 
8724       ierr = DMGetCoordinateDM(rdm, &cdm);CHKERRQ(ierr);
8725       ierr = DMCreateGlobalVector(cdm, &aux);CHKERRQ(ierr);
8726       ierr = DMGetDefaultSF(cdm, &sf);CHKERRQ(ierr);
8727       ierr = VecGetArrayRead(coordinatesNew, &lArray);CHKERRQ(ierr);
8728       ierr = VecSet(aux, PETSC_MIN_REAL);CHKERRQ(ierr);
8729       ierr = VecGetArray(aux, &gArray);CHKERRQ(ierr);
8730 #if defined(PETSC_USE_COMPLEX)
8731       ierr = VecGetLocalSize(aux, &gn);CHKERRQ(ierr);
8732       ierr = VecGetLocalSize(coordinatesNew, &ln);CHKERRQ(ierr);
8733       ierr = PetscMalloc2(ln,&lrArray,gn,&grArray);CHKERRQ(ierr);
8734       for (i=0;i<ln;i++) lrArray[i] = PetscRealPart(lArray[i]);
8735       for (i=0;i<gn;i++) grArray[i] = PetscRealPart(gArray[i]);
8736       ierr = PetscSFReduceBegin(sf, MPIU_REAL, lrArray, grArray, MPIU_MAX);CHKERRQ(ierr);
8737       ierr = PetscSFReduceEnd(sf, MPIU_REAL, lrArray, grArray, MPIU_MAX);CHKERRQ(ierr);
8738       for (i=0;i<gn;i++) gArray[i] = grArray[i];
8739       ierr = PetscFree2(lrArray,grArray);CHKERRQ(ierr);
8740 #else
8741       ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_MAX);CHKERRQ(ierr);
8742       ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_MAX);CHKERRQ(ierr);
8743 #endif
8744       ierr = VecRestoreArrayRead(coordinatesNew, &lArray);CHKERRQ(ierr);
8745       ierr = VecRestoreArray(aux, &gArray);CHKERRQ(ierr);
8746       ierr = DMGlobalToLocalBegin(cdm, aux, INSERT_VALUES, coordinatesNew);CHKERRQ(ierr);
8747       ierr = DMGlobalToLocalEnd(cdm, aux, INSERT_VALUES, coordinatesNew);CHKERRQ(ierr);
8748       ierr = VecDestroy(&aux);CHKERRQ(ierr);
8749     }
8750   }
8751   ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr);
8752   ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr);
8753   ierr = PetscFree(parentId);CHKERRQ(ierr);
8754   PetscFunctionReturn(0);
8755 }
8756 
8757 /*@
8758   DMPlexCreateProcessSF - Create an SF which just has process connectivity
8759 
8760   Collective on DM
8761 
8762   Input Parameters:
8763 + dm      - The DM
8764 - sfPoint - The PetscSF which encodes point connectivity
8765 
8766   Output Parameters:
8767 + processRanks - A list of process neighbors, or NULL
8768 - sfProcess    - An SF encoding the process connectivity, or NULL
8769 
8770   Level: developer
8771 
8772 .seealso: PetscSFCreate(), DMPlexCreateTwoSidedProcessSF()
8773 @*/
8774 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
8775 {
8776   PetscInt           numRoots, numLeaves, l;
8777   const PetscInt    *localPoints;
8778   const PetscSFNode *remotePoints;
8779   PetscInt          *localPointsNew;
8780   PetscSFNode       *remotePointsNew;
8781   PetscInt          *ranks, *ranksNew;
8782   PetscMPIInt        size;
8783   PetscErrorCode     ierr;
8784 
8785   PetscFunctionBegin;
8786   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8787   PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2);
8788   if (processRanks) {PetscValidPointer(processRanks, 3);}
8789   if (sfProcess)    {PetscValidPointer(sfProcess, 4);}
8790   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRQ(ierr);
8791   ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
8792   ierr = PetscMalloc1(numLeaves, &ranks);CHKERRQ(ierr);
8793   for (l = 0; l < numLeaves; ++l) {
8794     ranks[l] = remotePoints[l].rank;
8795   }
8796   ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr);
8797   ierr = PetscMalloc1(numLeaves, &ranksNew);CHKERRQ(ierr);
8798   ierr = PetscMalloc1(numLeaves, &localPointsNew);CHKERRQ(ierr);
8799   ierr = PetscMalloc1(numLeaves, &remotePointsNew);CHKERRQ(ierr);
8800   for (l = 0; l < numLeaves; ++l) {
8801     ranksNew[l]              = ranks[l];
8802     localPointsNew[l]        = l;
8803     remotePointsNew[l].index = 0;
8804     remotePointsNew[l].rank  = ranksNew[l];
8805   }
8806   ierr = PetscFree(ranks);CHKERRQ(ierr);
8807   if (processRanks) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);}
8808   else              {ierr = PetscFree(ranksNew);CHKERRQ(ierr);}
8809   if (sfProcess) {
8810     ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr);
8811     ierr = PetscObjectSetName((PetscObject) *sfProcess, "Process SF");CHKERRQ(ierr);
8812     ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr);
8813     ierr = PetscSFSetGraph(*sfProcess, size, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
8814   }
8815   PetscFunctionReturn(0);
8816 }
8817 
8818 static PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
8819 {
8820   PetscSF            sf, sfNew, sfProcess;
8821   IS                 processRanks;
8822   MPI_Datatype       depthType;
8823   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
8824   const PetscInt    *localPoints, *neighbors;
8825   const PetscSFNode *remotePoints;
8826   PetscInt          *localPointsNew;
8827   PetscSFNode       *remotePointsNew;
8828   PetscInt          *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
8829   PetscInt           ldepth, depth, numNeighbors, pStartNew, pEndNew, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r, n;
8830   PetscInt           cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
8831   PetscErrorCode     ierr;
8832 
8833   PetscFunctionBegin;
8834   ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr);
8835   ierr = DMPlexGetDepth(dm, &ldepth);CHKERRQ(ierr);
8836   ierr = MPIU_Allreduce(&ldepth, &depth, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr);
8837   if ((ldepth >= 0) && (depth != ldepth)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %D != %D", ldepth, depth);
8838   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
8839   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
8840   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
8841   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
8842   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
8843   cMax = cMax < 0 ? cEnd : cMax;
8844   fMax = fMax < 0 ? fEnd : fMax;
8845   eMax = eMax < 0 ? eEnd : eMax;
8846   if (refiner) {ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);}
8847   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
8848   ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr);
8849   /* Calculate size of new SF */
8850   ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
8851   if (numRoots < 0) PetscFunctionReturn(0);
8852   for (l = 0; l < numLeaves; ++l) {
8853     const PetscInt p = localPoints[l];
8854 
8855     switch (refiner) {
8856     case REFINER_SIMPLEX_1D:
8857       if ((p >= vStart) && (p < vEnd)) {
8858         /* Interior vertices stay the same */
8859         ++numLeavesNew;
8860       } else if ((p >= cStart && p < cMax)) {
8861         /* Interior cells add new cells and interior vertices */
8862         numLeavesNew += 2 + 1;
8863       }
8864       break;
8865     case REFINER_SIMPLEX_2D:
8866     case REFINER_HYBRID_SIMPLEX_2D:
8867       if ((p >= vStart) && (p < vEnd)) {
8868         /* Interior vertices stay the same */
8869         ++numLeavesNew;
8870       } else if ((p >= fStart) && (p < fMax)) {
8871         /* Interior faces add new faces and vertex */
8872         numLeavesNew += 2 + 1;
8873       } else if ((p >= fMax) && (p < fEnd)) {
8874         /* Hybrid faces stay the same */
8875         ++numLeavesNew;
8876       } else if ((p >= cStart) && (p < cMax)) {
8877         /* Interior cells add new cells and interior faces */
8878         numLeavesNew += 4 + 3;
8879       } else if ((p >= cMax) && (p < cEnd)) {
8880         /* Hybrid cells add new cells and hybrid face */
8881         numLeavesNew += 2 + 1;
8882       }
8883       break;
8884     case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
8885     case REFINER_SIMPLEX_TO_HEX_2D:
8886       if ((p >= vStart) && (p < vEnd)) {
8887         /* Interior vertices stay the same */
8888         ++numLeavesNew;
8889       } else if ((p >= fStart) && (p < fEnd)) {
8890         /* Interior faces add new faces and vertex */
8891         numLeavesNew += 2 + 1;
8892       } else if ((p >= cStart) && (p < cMax)) {
8893         /* Interior cells add new cells, interior faces, and vertex */
8894         numLeavesNew += 3 + 3 + 1;
8895       } else if ((p >= cMax) && (p < cEnd)) {
8896         /* Hybrid cells add new cells, interior faces, and vertex */
8897         numLeavesNew += 4 + 4 + 1;
8898       }
8899       break;
8900     case REFINER_HEX_2D:
8901     case REFINER_HYBRID_HEX_2D:
8902       if ((p >= vStart) && (p < vEnd)) {
8903         /* Interior vertices stay the same */
8904         ++numLeavesNew;
8905       } else if ((p >= fStart) && (p < fMax)) {
8906         /* Interior faces add new faces and vertex */
8907         numLeavesNew += 2 + 1;
8908       } else if ((p >= fMax) && (p < fEnd)) {
8909         /* Hybrid faces stay the same */
8910         ++numLeavesNew;
8911       } else if ((p >= cStart) && (p < cMax)) {
8912         /* Interior cells add new cells, interior faces, and vertex */
8913         numLeavesNew += 4 + 4 + 1;
8914       } else if ((p >= cMax) && (p < cEnd)) {
8915         /* Hybrid cells add new cells and hybrid face */
8916         numLeavesNew += 2 + 1;
8917       }
8918       break;
8919     case REFINER_SIMPLEX_3D:
8920     case REFINER_HYBRID_SIMPLEX_3D:
8921       if ((p >= vStart) && (p < vEnd)) {
8922         /* Interior vertices stay the same */
8923         ++numLeavesNew;
8924       } else if ((p >= eStart) && (p < eMax)) {
8925         /* Interior edges add new edges and vertex */
8926         numLeavesNew += 2 + 1;
8927       } else if ((p >= eMax) && (p < eEnd)) {
8928         /* Hybrid edges stay the same */
8929         ++numLeavesNew;
8930       } else if ((p >= fStart) && (p < fMax)) {
8931         /* Interior faces add new faces and edges */
8932         numLeavesNew += 4 + 3;
8933       } else if ((p >= fMax) && (p < fEnd)) {
8934         /* Hybrid faces add new faces and edges */
8935         numLeavesNew += 2 + 1;
8936       } else if ((p >= cStart) && (p < cMax)) {
8937         /* Interior cells add new cells, faces, and edges */
8938         numLeavesNew += 8 + 8 + 1;
8939       } else if ((p >= cMax) && (p < cEnd)) {
8940         /* Hybrid cells add new cells and faces */
8941         numLeavesNew += 4 + 3;
8942       }
8943       break;
8944     case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
8945     case REFINER_SIMPLEX_TO_HEX_3D:
8946       if ((p >= vStart) && (p < vEnd)) {
8947         /* Interior vertices stay the same */
8948         ++numLeavesNew;
8949       } else if ((p >= eStart) && (p < eMax)) {
8950         /* Interior edges add new edges and vertex */
8951         numLeavesNew += 2 + 1;
8952       } else if ((p >= eMax) && (p < eEnd)) {
8953         /* Hybrid edges stay the same */
8954         ++numLeavesNew;
8955       } else if ((p >= fStart) && (p < fMax)) {
8956         /* Interior faces add new faces, edges and a vertex */
8957         numLeavesNew += 3 + 3 + 1;
8958       } else if ((p >= fMax) && (p < fEnd)) {
8959         /* Hybrid faces add new faces and an edge */
8960         numLeavesNew += 2 + 1;
8961       } else if ((p >= cStart) && (p < cMax)) {
8962         /* Interior cells add new cells, faces, edges and a vertex */
8963         numLeavesNew += 4 + 6 + 4 + 1;
8964       } else if ((p >= cMax) && (p < cEnd)) {
8965         /* Hybrid cells add new cells, faces and an edge */
8966         numLeavesNew += 3 + 3 + 1;
8967       }
8968       break;
8969     case REFINER_HEX_3D:
8970     case REFINER_HYBRID_HEX_3D:
8971       if ((p >= vStart) && (p < vEnd)) {
8972         /* Old vertices stay the same */
8973         ++numLeavesNew;
8974       } else if ((p >= eStart) && (p < eMax)) {
8975         /* Interior edges add new edges, and vertex */
8976         numLeavesNew += 2 + 1;
8977       } else if ((p >= eMax) && (p < eEnd)) {
8978         /* Hybrid edges stay the same */
8979         ++numLeavesNew;
8980       } else if ((p >= fStart) && (p < fMax)) {
8981         /* Interior faces add new faces, edges, and vertex */
8982         numLeavesNew += 4 + 4 + 1;
8983       } else if ((p >= fMax) && (p < fEnd)) {
8984         /* Hybrid faces add new faces and edges */
8985         numLeavesNew += 2 + 1;
8986       } else if ((p >= cStart) && (p < cMax)) {
8987         /* Interior cells add new cells, faces, edges, and vertex */
8988         numLeavesNew += 8 + 12 + 6 + 1;
8989       } else if ((p >= cStart) && (p < cEnd)) {
8990         /* Hybrid cells add new cells, faces, and edges */
8991         numLeavesNew += 4 + 4 + 1;
8992       }
8993       break;
8994     default:
8995       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
8996     }
8997   }
8998   /* Communicate depthSizes for each remote rank */
8999   ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr);
9000   ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr);
9001   ierr = PetscMalloc5((depth+1)*numNeighbors,&rdepthSize,numNeighbors,&rvStartNew,numNeighbors,&reStartNew,numNeighbors,&rfStartNew,numNeighbors,&rcStartNew);CHKERRQ(ierr);
9002   ierr = PetscMalloc7(depth+1,&depthSizeOld,(depth+1)*numNeighbors,&rdepthSizeOld,(depth+1)*numNeighbors,&rdepthMaxOld,numNeighbors,&rvStart,numNeighbors,&reStart,numNeighbors,&rfStart,numNeighbors,&rcStart);CHKERRQ(ierr);
9003   ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr);
9004   ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr);
9005   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
9006   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
9007   for (n = 0; n < numNeighbors; ++n) {
9008     ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr);
9009   }
9010   depthSizeOld[depth]   = cMax;
9011   depthSizeOld[0]       = vMax;
9012   depthSizeOld[depth-1] = fMax;
9013   depthSizeOld[1]       = eMax;
9014 
9015   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
9016   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
9017 
9018   depthSizeOld[depth]   = cEnd - cStart;
9019   depthSizeOld[0]       = vEnd - vStart;
9020   depthSizeOld[depth-1] = fEnd - fStart;
9021   depthSizeOld[1]       = eEnd - eStart;
9022 
9023   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
9024   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
9025   for (n = 0; n < numNeighbors; ++n) {
9026     ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr);
9027     rdepthMaxOld[n*(depth+1)+depth]   = rdepthMaxOld[n*(depth+1)+depth]   < 0 ? rdepthSizeOld[n*(depth+1)+depth]  +rcStart[n]: rdepthMaxOld[n*(depth+1)+depth];
9028     rdepthMaxOld[n*(depth+1)+depth-1] = rdepthMaxOld[n*(depth+1)+depth-1] < 0 ? rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n]: rdepthMaxOld[n*(depth+1)+depth-1];
9029     rdepthMaxOld[n*(depth+1)+1]       = rdepthMaxOld[n*(depth+1)+1]       < 0 ? rdepthSizeOld[n*(depth+1)+1]      +reStart[n]: rdepthMaxOld[n*(depth+1)+1];
9030   }
9031   ierr = MPI_Type_free(&depthType);CHKERRQ(ierr);
9032   ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr);
9033   /* Calculate new point SF */
9034   ierr = PetscMalloc1(numLeavesNew, &localPointsNew);CHKERRQ(ierr);
9035   ierr = PetscMalloc1(numLeavesNew, &remotePointsNew);CHKERRQ(ierr);
9036   ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr);
9037   for (l = 0, m = 0; l < numLeaves; ++l) {
9038     PetscInt    p     = localPoints[l];
9039     PetscInt    rp    = remotePoints[l].index, n;
9040     PetscMPIInt rrank = remotePoints[l].rank;
9041 
9042     ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr);
9043     if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %D", rrank);
9044     switch (refiner) {
9045     case REFINER_SIMPLEX_1D:
9046       if ((p >= vStart) && (p < vEnd)) {
9047         /* Old vertices stay the same */
9048         localPointsNew[m]        = vStartNew     + (p  - vStart);
9049         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9050         remotePointsNew[m].rank  = rrank;
9051         ++m;
9052       } else if ((p >= cStart) && (p < cMax)) {
9053         /* Old interior cells add new cells and vertex */
9054         for (r = 0; r < 2; ++r, ++m) {
9055           localPointsNew[m]        = cStartNew     + (p  - cStart)*2     + r;
9056           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*2 + r;
9057           remotePointsNew[m].rank  = rrank;
9058         }
9059         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - cStart);
9060         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rcStart[n]);
9061         remotePointsNew[m].rank  = rrank;
9062         ++m;
9063       }
9064       break;
9065     case REFINER_SIMPLEX_2D:
9066     case REFINER_HYBRID_SIMPLEX_2D:
9067       if ((p >= vStart) && (p < vEnd)) {
9068         /* Old vertices stay the same */
9069         localPointsNew[m]        = vStartNew     + (p  - vStart);
9070         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9071         remotePointsNew[m].rank  = rrank;
9072         ++m;
9073       } else if ((p >= fStart) && (p < fMax)) {
9074         /* Old interior faces add new faces and vertex */
9075         for (r = 0; r < 2; ++r, ++m) {
9076           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
9077           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
9078           remotePointsNew[m].rank  = rrank;
9079         }
9080         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
9081         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
9082         remotePointsNew[m].rank  = rrank;
9083         ++m;
9084       } else if ((p >= fMax) && (p < fEnd)) {
9085         /* Old hybrid faces stay the same */
9086         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - fMax);
9087         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
9088         remotePointsNew[m].rank  = rrank;
9089         ++m;
9090       } else if ((p >= cStart) && (p < cMax)) {
9091         /* Old interior cells add new cells and interior faces */
9092         for (r = 0; r < 4; ++r, ++m) {
9093           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
9094           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
9095           remotePointsNew[m].rank  = rrank;
9096         }
9097         for (r = 0; r < 3; ++r, ++m) {
9098           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - cStart)*3     + r;
9099           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r;
9100           remotePointsNew[m].rank  = rrank;
9101         }
9102       } else if ((p >= cMax) && (p < cEnd)) {
9103         /* Old hybrid cells add new cells and hybrid face */
9104         for (r = 0; r < 2; ++r, ++m) {
9105           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
9106           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
9107           remotePointsNew[m].rank  = rrank;
9108         }
9109         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (cMax                            - cStart)*3     + (p  - cMax);
9110         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]);
9111         remotePointsNew[m].rank  = rrank;
9112         ++m;
9113       }
9114       break;
9115     case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
9116     case REFINER_SIMPLEX_TO_HEX_2D:
9117       if ((p >= vStart) && (p < vEnd)) {
9118         /* Old vertices stay the same */
9119         localPointsNew[m]        = vStartNew     + (p  - vStart);
9120         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9121         remotePointsNew[m].rank  = rrank;
9122         ++m;
9123       } else if ((p >= fStart) && (p < fEnd)) {
9124         /* Old interior faces add new faces and vertex */
9125         for (r = 0; r < 2; ++r, ++m) {
9126           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
9127           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
9128           remotePointsNew[m].rank  = rrank;
9129         }
9130         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
9131         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
9132         remotePointsNew[m].rank  = rrank;
9133         ++m;
9134       } else if ((p >= cStart) && (p < cMax)) {
9135         /* Old interior cells add new cells, interior faces, and a vertex */
9136         for (r = 0; r < 3; ++r, ++m) {
9137           localPointsNew[m]        = cStartNew     + (p  - cStart)*3     + r;
9138           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*3 + r;
9139           remotePointsNew[m].rank  = rrank;
9140         }
9141         for (r = 0; r < 3; ++r, ++m) {
9142           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*3     + r;
9143           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r;
9144           remotePointsNew[m].rank  = rrank;
9145         }
9146         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (fEnd - fStart)                    + (p  - cStart);
9147         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]);
9148         remotePointsNew[m].rank  = rrank;
9149         ++m;
9150       } else if ((p >= cMax) && (p < cEnd)) {
9151         /* Old interior hybrid cells add new cells, interior faces, and a vertex */
9152         for (r = 0; r < 4; ++r, ++m) {
9153           localPointsNew[m]        = cStartNew     + (cMax  - cStart)*3                               + (p  - cMax)*4 + r;
9154           remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*3 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
9155           remotePointsNew[m].rank  = rrank;
9156         }
9157         for (r = 0; r < 4; ++r, ++m) {
9158           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (cMax  - cStart)*3                               + (p - cMax)*4 + r;
9159           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*3 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
9160           remotePointsNew[m].rank  = rrank;
9161         }
9162         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (fEnd - fStart)                    + (p  - cStart);
9163         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]);
9164         remotePointsNew[m].rank  = rrank;
9165         ++m;
9166       }
9167       break;
9168     case REFINER_HEX_2D:
9169     case REFINER_HYBRID_HEX_2D:
9170       if ((p >= vStart) && (p < vEnd)) {
9171         /* Old vertices stay the same */
9172         localPointsNew[m]        = vStartNew     + (p  - vStart);
9173         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9174         remotePointsNew[m].rank  = rrank;
9175         ++m;
9176       } else if ((p >= fStart) && (p < fMax)) {
9177         /* Old interior faces add new faces and vertex */
9178         for (r = 0; r < 2; ++r, ++m) {
9179           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
9180           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
9181           remotePointsNew[m].rank  = rrank;
9182         }
9183         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
9184         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
9185         remotePointsNew[m].rank  = rrank;
9186         ++m;
9187       } else if ((p >= fMax) && (p < fEnd)) {
9188         /* Old hybrid faces stay the same */
9189         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - fMax);
9190         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
9191         remotePointsNew[m].rank  = rrank;
9192         ++m;
9193       } else if ((p >= cStart) && (p < cMax)) {
9194         /* Old interior cells add new cells, interior faces, and vertex */
9195         for (r = 0; r < 4; ++r, ++m) {
9196           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
9197           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
9198           remotePointsNew[m].rank  = rrank;
9199         }
9200         for (r = 0; r < 4; ++r, ++m) {
9201           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - cStart)*4     + r;
9202           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*4 + r;
9203           remotePointsNew[m].rank  = rrank;
9204         }
9205         localPointsNew[m]        = vStartNew     + (vEnd - vStart)               + (fMax                              - fStart)     + (p  - cStart);
9206         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0]  + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]);
9207         remotePointsNew[m].rank  = rrank;
9208         ++m;
9209       } else if ((p >= cStart) && (p < cMax)) {
9210         /* Old hybrid cells add new cells and hybrid face */
9211         for (r = 0; r < 2; ++r, ++m) {
9212           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r; /* TODO: is this a bug? */
9213           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; /* TODO: is this a bug? */
9214           remotePointsNew[m].rank  = rrank;
9215         }
9216         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (cMax                            - cStart)*4     + (p  - cMax);
9217         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*4 + (rp - rdepthMaxOld[n*(depth+1)+depth]);
9218         remotePointsNew[m].rank  = rrank;
9219         ++m;
9220       }
9221       break;
9222     case REFINER_SIMPLEX_3D:
9223     case REFINER_HYBRID_SIMPLEX_3D:
9224       if ((p >= vStart) && (p < vEnd)) {
9225         /* Interior vertices stay the same */
9226         localPointsNew[m]        = vStartNew     + (p  - vStart);
9227         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9228         remotePointsNew[m].rank  = rrank;
9229         ++m;
9230       } else if ((p >= eStart) && (p < eMax)) {
9231         /* Interior edges add new edges and vertex */
9232         for (r = 0; r < 2; ++r, ++m) {
9233           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
9234           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
9235           remotePointsNew[m].rank  = rrank;
9236         }
9237         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
9238         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
9239         remotePointsNew[m].rank  = rrank;
9240         ++m;
9241       } else if ((p >= eMax) && (p < eEnd)) {
9242         /* Hybrid edges stay the same */
9243         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (cMax                            - cStart)     + (p  - eMax);
9244         remotePointsNew[m].index = reStartNew[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]);
9245         remotePointsNew[m].rank  = rrank;
9246         ++m;
9247       } else if ((p >= fStart) && (p < fMax)) {
9248         /* Interior faces add new faces and edges */
9249         for (r = 0; r < 4; ++r, ++m) {
9250           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
9251           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
9252           remotePointsNew[m].rank  = rrank;
9253         }
9254         for (r = 0; r < 3; ++r, ++m) {
9255           localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (p  - fStart)*3     + r;
9256           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*3 + r;
9257           remotePointsNew[m].rank  = rrank;
9258         }
9259       } else if ((p >= fMax) && (p < fEnd)) {
9260         /* Hybrid faces add new faces and edges */
9261         for (r = 0; r < 2; ++r, ++m) {
9262           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (p  - fMax)*2                              + r;
9263           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth-1])*2 + r;
9264           remotePointsNew[m].rank  = rrank;
9265         }
9266         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (cMax                            - cStart)     + (eEnd                                    - eMax)                        + (p  - fMax);
9267         remotePointsNew[m].index = reStartNew[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]) + (rdepthSizeOld[n*(depth+1)+1]+reStart[n] - rdepthMaxOld[n*(depth+1)+1]) + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
9268         remotePointsNew[m].rank  = rrank;
9269         ++m;
9270       } else if ((p >= cStart) && (p < cMax)) {
9271         /* Interior cells add new cells, faces, and edges */
9272         for (r = 0; r < 8; ++r, ++m) {
9273           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
9274           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
9275           remotePointsNew[m].rank  = rrank;
9276         }
9277         for (r = 0; r < 8; ++r, ++m) {
9278           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (p  - cStart)*8     + r;
9279           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*8 + r;
9280           remotePointsNew[m].rank  = rrank;
9281         }
9282         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (p  - cStart)*1     + 0;
9283         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 + 0;
9284         remotePointsNew[m].rank  = rrank;
9285         ++m;
9286       } else if ((p >= cMax) && (p < cEnd)) {
9287         /* Hybrid cells add new cells and faces */
9288         for (r = 0; r < 4; ++r, ++m) {
9289           localPointsNew[m]        = cStartNew     + (cMax                            - cStart)*8     + (p  - cMax)*4                            + r;
9290           remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
9291           remotePointsNew[m].rank  = rrank;
9292         }
9293         for (r = 0; r < 3; ++r, ++m) {
9294           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (fEnd                                          - fMax)*2                              + (p  - cMax)*3                            + r;
9295           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])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth])*3 + r;
9296           remotePointsNew[m].rank  = rrank;
9297         }
9298       }
9299       break;
9300     case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
9301     case REFINER_SIMPLEX_TO_HEX_3D:
9302       if ((p >= vStart) && (p < vEnd)) {
9303         /* Interior vertices stay the same */
9304         localPointsNew[m]        = vStartNew     + (p  - vStart);
9305         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9306         remotePointsNew[m].rank  = rrank;
9307         ++m;
9308       } else if ((p >= eStart) && (p < eMax)) {
9309         /* Interior edges add new edges and vertex */
9310         for (r = 0; r < 2; ++r, ++m) {
9311           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
9312           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
9313           remotePointsNew[m].rank  = rrank;
9314         }
9315         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
9316         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
9317         remotePointsNew[m].rank  = rrank;
9318         ++m;
9319       } else if ((p >= eMax) && (p < eEnd)) {
9320         /* Hybrid edges stay the same */
9321         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (cMax                            - cStart)*4     + (p  - eMax);
9322         remotePointsNew[m].index = reStartNew[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])*4 + (rp - rdepthMaxOld[n*(depth+1)+1]);
9323         remotePointsNew[m].rank  = rrank;
9324         ++m;
9325       } else if ((p >= fStart) && (p < fMax)) {
9326         /* Interior faces add new faces, edges and a vertex */
9327         for (r = 0; r < 3; ++r, ++m) {
9328           localPointsNew[m]        = fStartNew     + (p  - fStart)*3     + r;
9329           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*3 + r;
9330           remotePointsNew[m].rank  = rrank;
9331         }
9332         for (r = 0; r < 3; ++r, ++m) {
9333           localPointsNew[m]        = eStartNew     + (eMax - eStart)*2                            + (p  - fStart)*3     + r;
9334           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*3 + r;
9335           remotePointsNew[m].rank  = rrank;
9336         }
9337         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (eMax - eStart)                            + (p - fStart);
9338         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rp - rfStart[n]);
9339         remotePointsNew[m].rank  = rrank;
9340         ++m;
9341       } else if ((p >= fMax) && (p < fEnd)) {
9342         /* Interior hybrid faces add new faces and an edge */
9343         for (r = 0; r < 2; ++r, ++m) {
9344           localPointsNew[m]        = fStartNew     + (fMax - fStart)*3                                 + (cMax - cStart)*6                                + (p  - fMax)*2 + r;
9345           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1]- rfStart[n])*3 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*6 + (rp - rdepthMaxOld[n*(depth+1)+depth-1])*2 + r;
9346           remotePointsNew[m].rank  = rrank;
9347         }
9348         localPointsNew[m]        = eStartNew     + (eMax - eStart)*2                            + (fMax - fStart)*3                                 + (cMax - cStart)*4                                + (eEnd - eMax)                                                           + (p  - fMax);
9349         remotePointsNew[m].index = reStartNew[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])*4 + (rdepthSizeOld[n*(depth+1)+1]+reStart[n] - rdepthMaxOld[n*(depth+1)+1]) + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
9350         remotePointsNew[m].rank  = rrank;
9351         ++m;
9352       } else if ((p >= cStart) && (p < cMax)) {
9353         /* Interior cells add new cells, faces, edges, and a vertex */
9354         for (r = 0; r < 4; ++r, ++m) {
9355           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
9356           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
9357           remotePointsNew[m].rank  = rrank;
9358         }
9359         for (r = 0; r < 6; ++r, ++m) {
9360           localPointsNew[m]        = fStartNew     + (fMax - fStart)*3                                 + (p  - cStart)*6     + r;
9361           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1]- rfStart[n])*3 + (rp - rcStart[n])*6 + r;
9362           remotePointsNew[m].rank  = rrank;
9363         }
9364         for (r = 0; r < 4; ++r, ++m) {
9365           localPointsNew[m]        = eStartNew     + (eMax - eStart)*2                           + (fMax - fStart)*3                                 + (p  - cStart)*4 + r;
9366           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])*4 + r;
9367           remotePointsNew[m].rank  = rrank;
9368         }
9369         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (eMax - eStart)                           + (fMax - fStart)                                 + (p  - cStart);
9370         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+1]- reStart[n]) + (rdepthMaxOld[n*(depth+1)+depth-1]- rfStart[n]) + (rp - rcStart[n]);
9371         remotePointsNew[m].rank  = rrank;
9372         ++m;
9373       } else if ((p >= cMax) && (p < cEnd)) {
9374         /* Interior hybrid cells add new cells, faces and an edge */
9375         for (r = 0; r < 3; ++r, ++m) {
9376           localPointsNew[m]        = cStartNew     + (cMax                            - cStart)*4     + (p  - cMax)*3                            + r;
9377           remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*4 + (rp - rdepthMaxOld[n*(depth+1)+depth])*3 + r;
9378           remotePointsNew[m].rank  = rrank;
9379         }
9380         for (r = 0; r < 3; ++r, ++m) {
9381           localPointsNew[m]        = fStartNew     + (fMax - fStart)*3                                 + (cMax - cStart)*6                                + (fEnd  - fMax)*2                                                                      + (p  - cMax)*3 + r;
9382           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1]- rfStart[n])*3 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*6 + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth])*3 + r;
9383           remotePointsNew[m].rank  = rrank;
9384         }
9385         localPointsNew[m]        = eStartNew     + (eMax - eStart)*2                           + (fMax - fStart)*3                                 + (cMax - cStart)*4                                + (eEnd  - eMax)                                                          + (fEnd  - fMax)                                                                      + (p  - cMax);
9386         remotePointsNew[m].index = reStartNew[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])*4 + (rdepthSizeOld[n*(depth+1)+1]+reStart[n] - rdepthMaxOld[n*(depth+1)+1]) + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1]) + (rp - rdepthMaxOld[n*(depth+1)+depth]);
9387         remotePointsNew[m].rank  = rrank;
9388         ++m;
9389       }
9390       break;
9391     case REFINER_HEX_3D:
9392     case REFINER_HYBRID_HEX_3D:
9393       if ((p >= vStart) && (p < vEnd)) {
9394         /* Interior vertices stay the same */
9395         localPointsNew[m]        = vStartNew     + (p  - vStart);
9396         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9397         remotePointsNew[m].rank  = rrank;
9398         ++m;
9399       } else if ((p >= eStart) && (p < eMax)) {
9400         /* Interior edges add new edges and vertex */
9401         for (r = 0; r < 2; ++r, ++m) {
9402           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
9403           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
9404           remotePointsNew[m].rank  = rrank;
9405         }
9406         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
9407         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
9408         remotePointsNew[m].rank  = rrank;
9409         ++m;
9410       } else if ((p >= eMax) && (p < eEnd)) {
9411         /* Hybrid edges stay the same */
9412         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (cMax                            - cStart)*6     + (p  - eMax);
9413         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*6 + (rp - rdepthMaxOld[n*(depth+1)+1]);
9414         remotePointsNew[m].rank  = rrank;
9415         ++m;
9416       } else if ((p >= fStart) && (p < fMax)) {
9417         /* Interior faces add new faces, edges, and vertex */
9418         for (r = 0; r < 4; ++r, ++m) {
9419           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
9420           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
9421           remotePointsNew[m].rank  = rrank;
9422         }
9423         for (r = 0; r < 4; ++r, ++m) {
9424           localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (p  - fStart)*4     + r;
9425           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*4 + r;
9426           remotePointsNew[m].rank  = rrank;
9427         }
9428         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (eMax                        - eStart)     + (p  - fStart);
9429         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rp - rfStart[n]);
9430         remotePointsNew[m].rank  = rrank;
9431         ++m;
9432       } else if ((p >= fMax) && (p < fEnd)) {
9433         /* Hybrid faces add new faces and edges */
9434         for (r = 0; r < 2; ++r, ++m) {
9435           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*12     + (p  - fMax)*2                              + r;
9436           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*12 + (rp - rdepthMaxOld[n*(depth+1)+depth-1])*2 + r;
9437           remotePointsNew[m].rank  = rrank;
9438         }
9439         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (cMax                            - cStart)*6     + (eEnd                                    - eMax)                        + (p  - fMax);
9440         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*6 + (rdepthSizeOld[n*(depth+1)+1]+reStart[n] - rdepthMaxOld[n*(depth+1)+1]) + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
9441         remotePointsNew[m].rank  = rrank;
9442         ++m;
9443       } else if ((p >= cStart) && (p < cMax)) {
9444         /* Interior cells add new cells, faces, edges, and vertex */
9445         for (r = 0; r < 8; ++r, ++m) {
9446           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
9447           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
9448           remotePointsNew[m].rank  = rrank;
9449         }
9450         for (r = 0; r < 12; ++r, ++m) {
9451           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (p  - cStart)*12     + r;
9452           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*12 + r;
9453           remotePointsNew[m].rank  = rrank;
9454         }
9455         for (r = 0; r < 6; ++r, ++m) {
9456           localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (p  - cStart)*6     + r;
9457           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*6 + r;
9458           remotePointsNew[m].rank  = rrank;
9459         }
9460         for (r = 0; r < 1; ++r, ++m) {
9461           localPointsNew[m]        = vStartNew     + (eMax                        - eStart)     + (fMax                              - fStart)     + (p  - cStart)     + r;
9462           remotePointsNew[m].index = rvStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]) + r;
9463           remotePointsNew[m].rank  = rrank;
9464         }
9465       } else if ((p >= cMax) && (p < cEnd)) {
9466         /* Hybrid cells add new cells, faces, and edges */
9467         for (r = 0; r < 4; ++r, ++m) {
9468           localPointsNew[m]        = cStartNew     + (cMax                            - cStart)*8     + (p  - cMax)*4                            + r;
9469           remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
9470           remotePointsNew[m].rank  = rrank;
9471         }
9472         for (r = 0; r < 4; ++r, ++m) {
9473           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*12     + (fEnd                                          - fMax)*2                              + (p  - cMax)*4                            + r;
9474           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*12 + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
9475           remotePointsNew[m].rank  = rrank;
9476         }
9477         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (cMax                            - cStart)*6     + (eEnd                                    - eMax)                        + (fEnd                                          - fMax)                              + (p  - cMax);
9478         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*6 + (rdepthSizeOld[n*(depth+1)+1]+reStart[n] - rdepthMaxOld[n*(depth+1)+1]) + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1]) + (rp - rdepthMaxOld[n*(depth+1)+depth]);
9479         remotePointsNew[m].rank  = rrank;
9480         ++m;
9481       }
9482       break;
9483     default:
9484       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
9485     }
9486   }
9487   if (m != numLeavesNew) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of leaf point %D should be %D", m, numLeavesNew);
9488   ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr);
9489   ierr = ISDestroy(&processRanks);CHKERRQ(ierr);
9490   {
9491     PetscSFNode *rp, *rtmp;
9492     PetscInt    *lp, *idx, *ltmp, i;
9493 
9494     /* SF needs sorted leaves to correct calculate Gather */
9495     ierr = PetscMalloc1(numLeavesNew,&idx);CHKERRQ(ierr);
9496     ierr = PetscMalloc1(numLeavesNew, &lp);CHKERRQ(ierr);
9497     ierr = PetscMalloc1(numLeavesNew, &rp);CHKERRQ(ierr);
9498     for (i = 0; i < numLeavesNew; ++i) {
9499       if ((localPointsNew[i] < pStartNew) || (localPointsNew[i] >= pEndNew)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local SF point %D (%D) not in [%D, %D)", localPointsNew[i], i, pStartNew, pEndNew);
9500       idx[i] = i;
9501     }
9502     ierr = PetscSortIntWithPermutation(numLeavesNew, localPointsNew, idx);CHKERRQ(ierr);
9503     for (i = 0; i < numLeavesNew; ++i) {
9504       lp[i] = localPointsNew[idx[i]];
9505       rp[i] = remotePointsNew[idx[i]];
9506     }
9507     ltmp            = localPointsNew;
9508     localPointsNew  = lp;
9509     rtmp            = remotePointsNew;
9510     remotePointsNew = rp;
9511     ierr = PetscFree(idx);CHKERRQ(ierr);
9512     ierr = PetscFree(ltmp);CHKERRQ(ierr);
9513     ierr = PetscFree(rtmp);CHKERRQ(ierr);
9514   }
9515   ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
9516   ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr);
9517   ierr = PetscFree7(depthSizeOld,rdepthSizeOld,rdepthMaxOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr);
9518   PetscFunctionReturn(0);
9519 }
9520 
9521 static PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
9522 {
9523   PetscInt       numLabels, l;
9524   PetscInt       depth, newp, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r;
9525   PetscInt       cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
9526   PetscErrorCode ierr;
9527 
9528   PetscFunctionBegin;
9529   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
9530   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
9531   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
9532   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
9533   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
9534   if (refiner) {ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);}
9535   ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
9536   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
9537   switch (refiner) {
9538   case REFINER_NOOP:
9539   case REFINER_SIMPLEX_1D:
9540   case REFINER_SIMPLEX_2D:
9541   case REFINER_SIMPLEX_TO_HEX_2D:
9542   case REFINER_HEX_2D:
9543   case REFINER_SIMPLEX_3D:
9544   case REFINER_HEX_3D:
9545   case REFINER_SIMPLEX_TO_HEX_3D:
9546     break;
9547   case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
9548   case REFINER_HYBRID_SIMPLEX_3D:
9549   case REFINER_HYBRID_HEX_3D:
9550     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
9551   case REFINER_HYBRID_SIMPLEX_2D:
9552   case REFINER_HYBRID_HEX_2D:
9553     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
9554   case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
9555     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
9556     break;
9557   default:
9558     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
9559   }
9560   cMax = cMax < 0 ? cEnd : cMax;
9561   fMax = fMax < 0 ? fEnd : fMax;
9562   eMax = eMax < 0 ? eEnd : eMax;
9563   for (l = 0; l < numLabels; ++l) {
9564     DMLabel         label, labelNew;
9565     const char     *lname;
9566     PetscBool       isDepth;
9567     IS              valueIS;
9568     const PetscInt *values;
9569     PetscInt        defVal;
9570     PetscInt        numValues, val;
9571 
9572     ierr = DMGetLabelName(dm, l, &lname);CHKERRQ(ierr);
9573     ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr);
9574     if (isDepth) continue;
9575     ierr = DMCreateLabel(rdm, lname);CHKERRQ(ierr);
9576     ierr = DMGetLabel(dm, lname, &label);CHKERRQ(ierr);
9577     ierr = DMGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr);
9578     ierr = DMLabelGetDefaultValue(label,&defVal);CHKERRQ(ierr);
9579     ierr = DMLabelSetDefaultValue(labelNew,defVal);CHKERRQ(ierr);
9580     ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
9581     ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr);
9582     ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
9583     for (val = 0; val < numValues; ++val) {
9584       IS              pointIS;
9585       const PetscInt *points;
9586       PetscInt        numPoints, n;
9587 
9588       ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr);
9589       ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
9590       ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
9591       /* Ensure refined label is created with same number of strata as
9592        * original (even if no entries here). */
9593       ierr = DMLabelAddStratum(labelNew, values[val]);CHKERRQ(ierr);
9594       for (n = 0; n < numPoints; ++n) {
9595         const PetscInt p = points[n];
9596         switch (refiner) {
9597         case REFINER_SIMPLEX_1D:
9598           if ((p >= vStart) && (p < vEnd)) {
9599             /* Old vertices stay the same */
9600             newp = vStartNew + (p - vStart);
9601             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9602           } else if ((p >= cStart) && (p < cEnd)) {
9603             /* Old cells add new cells and vertex */
9604             newp = vStartNew + (vEnd - vStart) + (p - cStart);
9605             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9606             for (r = 0; r < 2; ++r) {
9607               newp = cStartNew + (p - cStart)*2 + r;
9608               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9609             }
9610           }
9611           break;
9612         case REFINER_SIMPLEX_2D:
9613           if ((p >= vStart) && (p < vEnd)) {
9614             /* Old vertices stay the same */
9615             newp = vStartNew + (p - vStart);
9616             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9617           } else if ((p >= fStart) && (p < fEnd)) {
9618             /* Old faces add new faces and vertex */
9619             newp = vStartNew + (vEnd - vStart) + (p - fStart);
9620             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9621             for (r = 0; r < 2; ++r) {
9622               newp = fStartNew + (p - fStart)*2 + r;
9623               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9624             }
9625           } else if ((p >= cStart) && (p < cEnd)) {
9626             /* Old cells add new cells and interior faces */
9627             for (r = 0; r < 4; ++r) {
9628               newp = cStartNew + (p - cStart)*4 + r;
9629               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9630             }
9631             for (r = 0; r < 3; ++r) {
9632               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
9633               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9634             }
9635           }
9636           break;
9637         case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
9638         case REFINER_SIMPLEX_TO_HEX_2D:
9639           if ((p >= vStart) && (p < vEnd)) {
9640             /* Old vertices stay the same */
9641             newp = vStartNew + (p - vStart);
9642             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9643           } else if ((p >= fStart) && (p < fEnd)) {
9644             /* Old faces add new faces and vertex */
9645             newp = vStartNew + (vEnd - vStart) + (p - fStart);
9646             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9647             for (r = 0; r < 2; ++r) {
9648               newp = fStartNew + (p - fStart)*2 + r;
9649               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9650             }
9651           } else if ((p >= cStart) && (p < cMax)) {
9652             /* Old cells add new cells, interior faces, and a vertex */
9653             for (r = 0; r < 3; ++r) {
9654               newp = cStartNew + (p - cStart)*3 + r;
9655               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9656             }
9657             for (r = 0; r < 3; ++r) {
9658               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
9659               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9660             }
9661             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + p;
9662             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9663           } else if ((p >= cMax) && (p < cEnd)) {
9664             /* Old hybrid cells add new cells, interior faces, and a vertex */
9665             for (r = 0; r < 4; ++r) {
9666               newp = cStartNew + (cMax - cStart)*3 + (p - cMax)*4 + r;
9667               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9668             }
9669             for (r = 0; r < 4; ++r) {
9670               newp = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (p - cMax)*4 + r;
9671               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9672             }
9673             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + p;
9674             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9675           }
9676           break;
9677         case REFINER_HEX_2D:
9678           if ((p >= vStart) && (p < vEnd)) {
9679             /* Old vertices stay the same */
9680             newp = vStartNew + (p - vStart);
9681             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9682           } else if ((p >= fStart) && (p < fEnd)) {
9683             /* Old faces add new faces and vertex */
9684             newp = vStartNew + (vEnd - vStart) + (p - fStart);
9685             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9686             for (r = 0; r < 2; ++r) {
9687               newp = fStartNew + (p - fStart)*2 + r;
9688               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9689             }
9690           } else if ((p >= cStart) && (p < cEnd)) {
9691             /* Old cells add new cells and interior faces and vertex */
9692             for (r = 0; r < 4; ++r) {
9693               newp = cStartNew + (p - cStart)*4 + r;
9694               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9695             }
9696             for (r = 0; r < 4; ++r) {
9697               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
9698               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9699             }
9700             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
9701             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9702           }
9703           break;
9704         case REFINER_HYBRID_SIMPLEX_2D:
9705           if ((p >= vStart) && (p < vEnd)) {
9706             /* Old vertices stay the same */
9707             newp = vStartNew + (p - vStart);
9708             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9709           } else if ((p >= fStart) && (p < fMax)) {
9710             /* Old interior faces add new faces and vertex */
9711             newp = vStartNew + (vEnd - vStart) + (p - fStart);
9712             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9713             for (r = 0; r < 2; ++r) {
9714               newp = fStartNew + (p - fStart)*2 + r;
9715               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9716             }
9717           } else if ((p >= fMax) && (p < fEnd)) {
9718             /* Old hybrid faces stay the same */
9719             newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
9720             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9721           } else if ((p >= cStart) && (p < cMax)) {
9722             /* Old interior cells add new cells and interior faces */
9723             for (r = 0; r < 4; ++r) {
9724               newp = cStartNew + (p - cStart)*4 + r;
9725               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9726             }
9727             for (r = 0; r < 3; ++r) {
9728               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
9729               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9730             }
9731           } else if ((p >= cMax) && (p < cEnd)) {
9732             /* Old hybrid cells add new cells and hybrid face */
9733             for (r = 0; r < 2; ++r) {
9734               newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
9735               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9736             }
9737             newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
9738             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9739           }
9740           break;
9741         case REFINER_HYBRID_HEX_2D:
9742           if ((p >= vStart) && (p < vEnd)) {
9743             /* Old vertices stay the same */
9744             newp = vStartNew + (p - vStart);
9745             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9746           } else if ((p >= fStart) && (p < fMax)) {
9747             /* Old interior faces add new faces and vertex */
9748             newp = vStartNew + (vEnd - vStart) + (p - fStart);
9749             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9750             for (r = 0; r < 2; ++r) {
9751               newp = fStartNew + (p - fStart)*2 + r;
9752               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9753             }
9754           } else if ((p >= fMax) && (p < fEnd)) {
9755             /* Old hybrid faces stay the same */
9756             newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
9757             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9758           } else if ((p >= cStart) && (p < cMax)) {
9759             /* Old interior cells add new cells, interior faces, and vertex */
9760             for (r = 0; r < 4; ++r) {
9761               newp = cStartNew + (p - cStart)*4 + r;
9762               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9763             }
9764             for (r = 0; r < 4; ++r) {
9765               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
9766               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9767             }
9768             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
9769             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9770           } else if ((p >= cMax) && (p < cEnd)) {
9771             /* Old hybrid cells add new cells and hybrid face */
9772             for (r = 0; r < 2; ++r) {
9773               newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
9774               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9775             }
9776             newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (p - cMax);
9777             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9778           }
9779           break;
9780         case REFINER_SIMPLEX_3D:
9781           if ((p >= vStart) && (p < vEnd)) {
9782             /* Old vertices stay the same */
9783             newp = vStartNew + (p - vStart);
9784             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9785           } else if ((p >= eStart) && (p < eEnd)) {
9786             /* Old edges add new edges and vertex */
9787             for (r = 0; r < 2; ++r) {
9788               newp = eStartNew + (p - eStart)*2 + r;
9789               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9790             }
9791             newp = vStartNew + (vEnd - vStart) + (p - eStart);
9792             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9793           } else if ((p >= fStart) && (p < fEnd)) {
9794             /* Old faces add new faces and edges */
9795             for (r = 0; r < 4; ++r) {
9796               newp = fStartNew + (p - fStart)*4 + r;
9797               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9798             }
9799             for (r = 0; r < 3; ++r) {
9800               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
9801               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9802             }
9803           } else if ((p >= cStart) && (p < cEnd)) {
9804             /* Old cells add new cells and interior faces and edges */
9805             for (r = 0; r < 8; ++r) {
9806               newp = cStartNew + (p - cStart)*8 + r;
9807               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9808             }
9809             for (r = 0; r < 8; ++r) {
9810               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*8 + r;
9811               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9812             }
9813             for (r = 0; r < 1; ++r) {
9814               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*1 + r;
9815               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9816             }
9817           }
9818           break;
9819         case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
9820         case REFINER_SIMPLEX_TO_HEX_3D:
9821           if ((p >= vStart) && (p < vEnd)) {
9822             /* Old vertices stay the same */
9823             newp = vStartNew + (p - vStart);
9824             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9825           } else if ((p >= eStart) && (p < eMax)) {
9826             /* Interior edges add new edges and vertex */
9827             for (r = 0; r < 2; ++r) {
9828               newp = eStartNew + (p - eStart)*2 + r;
9829               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9830             }
9831             newp = vStartNew + (vEnd - vStart) + (p - eStart);
9832             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9833           } else if ((p >= eMax) && (p < eEnd)) {
9834             /* Hybrid edges stay the same */
9835             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + p - eMax;
9836             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9837           } else if ((p >= fStart) && (p < fMax)) {
9838             /* Old faces add new faces, edges and a vertex */
9839             for (r = 0; r < 3; ++r) {
9840               newp = fStartNew + (p - fStart)*3 + r;
9841               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9842             }
9843             for (r = 0; r < 3; ++r) {
9844               newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
9845               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9846             }
9847           } else if ((p >= fMax) && (p < fEnd)) {
9848             /* Old hybrid faces add new faces and an edge */
9849             for (r = 0; r < 2; ++r) {
9850               newp = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (p - fMax)*2 + r;
9851               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9852             }
9853             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (p - fMax);
9854             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9855           } else if ((p >= cStart) && (p < cMax)) {
9856             /* Old cells add new cells and interior faces and edges and a vertex */
9857             for (r = 0; r < 4; ++r) {
9858               newp = cStartNew + (p - cStart)*4 + r;
9859               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9860             }
9861             for (r = 0; r < 6; ++r) {
9862               newp = fStartNew + (fMax - fStart)*3 + (p - cStart)*6 + r;
9863               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9864             }
9865             for (r = 0; r < 4; ++r) {
9866               newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart)*4 + r;
9867               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9868             }
9869             newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + p - cStart;
9870             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9871           } else if ((p >= cMax) && (p < cEnd)) {
9872             /* Old hybrid cells add new cells and interior faces and an edge */
9873             for (r = 0; r < 3; ++r) {
9874               newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*3 + r;
9875               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9876             }
9877             for (r = 0; r < 3; ++r) {
9878               newp = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
9879               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9880             }
9881             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + p - cMax;
9882             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9883           }
9884           break;
9885         case REFINER_HYBRID_SIMPLEX_3D:
9886           if ((p >= vStart) && (p < vEnd)) {
9887             /* Interior vertices stay the same */
9888             newp = vStartNew + (p - vStart);
9889             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9890           } else if ((p >= eStart) && (p < eMax)) {
9891             /* Interior edges add new edges and vertex */
9892             for (r = 0; r < 2; ++r) {
9893               newp = eStartNew + (p - eStart)*2 + r;
9894               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9895             }
9896             newp = vStartNew + (vEnd - vStart) + (p - eStart);
9897             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9898           } else if ((p >= eMax) && (p < eEnd)) {
9899             /* Hybrid edges stay the same */
9900             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - eMax);
9901             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9902           } else if ((p >= fStart) && (p < fMax)) {
9903             /* Interior faces add new faces and edges */
9904             for (r = 0; r < 4; ++r) {
9905               newp = fStartNew + (p - fStart)*4 + r;
9906               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9907             }
9908             for (r = 0; r < 3; ++r) {
9909               newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
9910               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9911             }
9912           } else if ((p >= fMax) && (p < fEnd)) {
9913             /* Hybrid faces add new faces and edges */
9914             for (r = 0; r < 2; ++r) {
9915               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (p - fMax)*2 + r;
9916               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9917             }
9918             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - fMax);
9919             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9920           } else if ((p >= cStart) && (p < cMax)) {
9921             /* Interior cells add new cells, faces, and edges */
9922             for (r = 0; r < 8; ++r) {
9923               newp = cStartNew + (p - cStart)*8 + r;
9924               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9925             }
9926             for (r = 0; r < 8; ++r) {
9927               newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*8 + r;
9928               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9929             }
9930             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart);
9931             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9932           } else if ((p >= cMax) && (p < cEnd)) {
9933             /* Hybrid cells add new cells and faces */
9934             for (r = 0; r < 4; ++r) {
9935               newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
9936               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9937             }
9938             for (r = 0; r < 3; ++r) {
9939               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
9940               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9941             }
9942           }
9943           break;
9944         case REFINER_HEX_3D:
9945           if ((p >= vStart) && (p < vEnd)) {
9946             /* Old vertices stay the same */
9947             newp = vStartNew + (p - vStart);
9948             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9949           } else if ((p >= eStart) && (p < eEnd)) {
9950             /* Old edges add new edges and vertex */
9951             for (r = 0; r < 2; ++r) {
9952               newp = eStartNew + (p - eStart)*2 + r;
9953               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9954             }
9955             newp = vStartNew + (vEnd - vStart) + (p - eStart);
9956             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9957           } else if ((p >= fStart) && (p < fEnd)) {
9958             /* Old faces add new faces, edges, and vertex */
9959             for (r = 0; r < 4; ++r) {
9960               newp = fStartNew + (p - fStart)*4 + r;
9961               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9962             }
9963             for (r = 0; r < 4; ++r) {
9964               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*4 + r;
9965               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9966             }
9967             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (p - fStart);
9968             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9969           } else if ((p >= cStart) && (p < cEnd)) {
9970             /* Old cells add new cells, faces, edges, and vertex */
9971             for (r = 0; r < 8; ++r) {
9972               newp = cStartNew + (p - cStart)*8 + r;
9973               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9974             }
9975             for (r = 0; r < 12; ++r) {
9976               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*12 + r;
9977               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9978             }
9979             for (r = 0; r < 6; ++r) {
9980               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (p - cStart)*6 + r;
9981               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9982             }
9983             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (p - cStart);
9984             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9985           }
9986           break;
9987         case REFINER_HYBRID_HEX_3D:
9988           if ((p >= vStart) && (p < vEnd)) {
9989             /* Interior vertices stay the same */
9990             newp = vStartNew + (p - vStart);
9991             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9992           } else if ((p >= eStart) && (p < eMax)) {
9993             /* Interior edges add new edges and vertex */
9994             for (r = 0; r < 2; ++r) {
9995               newp = eStartNew + (p - eStart)*2 + r;
9996               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
9997             }
9998             newp = vStartNew + (vEnd - vStart) + (p - eStart);
9999             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10000           } else if ((p >= eMax) && (p < eEnd)) {
10001             /* Hybrid edges stay the same */
10002             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - eMax);
10003             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10004           } else if ((p >= fStart) && (p < fMax)) {
10005             /* Interior faces add new faces, edges, and vertex */
10006             for (r = 0; r < 4; ++r) {
10007               newp = fStartNew + (p - fStart)*4 + r;
10008               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10009             }
10010             for (r = 0; r < 4; ++r) {
10011               newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*4 + r;
10012               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10013             }
10014             newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (p - fStart);
10015             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10016           } else if ((p >= fMax) && (p < fEnd)) {
10017             /* Hybrid faces add new faces and edges */
10018             for (r = 0; r < 2; ++r) {
10019               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (p - fMax)*2 + r;
10020               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10021             }
10022             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - fMax);
10023             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10024           } else if ((p >= cStart) && (p < cMax)) {
10025             /* Interior cells add new cells, faces, edges, and vertex */
10026             for (r = 0; r < 8; ++r) {
10027               newp = cStartNew + (p - cStart)*8 + r;
10028               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10029             }
10030             for (r = 0; r < 12; ++r) {
10031               newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*12 + r;
10032               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10033             }
10034             for (r = 0; r < 6; ++r) {
10035               newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (p - cStart)*6 + r;
10036               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10037             }
10038             newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (p - cStart);
10039             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10040           } else if ((p >= cMax) && (p < cEnd)) {
10041             /* Hybrid cells add new cells, faces, and edges */
10042             for (r = 0; r < 4; ++r) {
10043               newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
10044               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10045             }
10046             for (r = 0; r < 4; ++r) {
10047               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (p - cMax)*4 + r;
10048               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10049             }
10050             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (fEnd - fMax) + (p - cMax);
10051             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
10052           }
10053           break;
10054         default:
10055           SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
10056         }
10057       }
10058       ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
10059       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
10060     }
10061     ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
10062     ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
10063     if (0) {
10064       ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
10065     }
10066   }
10067   PetscFunctionReturn(0);
10068 }
10069 
10070 /* This will only work for interpolated meshes */
10071 PetscErrorCode DMPlexRefineUniform_Internal(DM dm, CellRefiner cellRefiner, DM *dmRefined)
10072 {
10073   DM             rdm;
10074   PetscInt      *depthSize;
10075   PetscInt       dim, depth = 0, d, pStart = 0, pEnd = 0;
10076   PetscErrorCode ierr;
10077 
10078   PetscFunctionBegin;
10079   ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr);
10080   ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr);
10081   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
10082   ierr = DMSetDimension(rdm, dim);CHKERRQ(ierr);
10083   /* Calculate number of new points of each depth */
10084   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
10085   if (depth >= 0 && dim != depth) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated for regular refinement");
10086   ierr = PetscMalloc1(depth+1, &depthSize);CHKERRQ(ierr);
10087   ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr);
10088   ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr);
10089   /* Step 1: Set chart */
10090   for (d = 0; d <= depth; ++d) pEnd += depthSize[d];
10091   ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr);
10092   /* Step 2: Set cone/support sizes (automatically stratifies) */
10093   ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
10094   /* Step 3: Setup refined DM */
10095   ierr = DMSetUp(rdm);CHKERRQ(ierr);
10096   /* Step 4: Set cones and supports (automatically symmetrizes) */
10097   ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
10098   /* Step 5: Create pointSF */
10099   ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
10100   /* Step 6: Create labels */
10101   ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
10102   /* Step 7: Set coordinates */
10103   ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
10104   ierr = PetscFree(depthSize);CHKERRQ(ierr);
10105 
10106   *dmRefined = rdm;
10107   PetscFunctionReturn(0);
10108 }
10109 
10110 /*@
10111   DMPlexCreateCoarsePointIS - Creates an IS covering the coarse DM chart with the fine points as data
10112 
10113   Input Parameter:
10114 . dm - The coarse DM
10115 
10116   Output Parameter:
10117 . fpointIS - The IS of all the fine points which exist in the original coarse mesh
10118 
10119   Level: developer
10120 
10121 .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexCreateSubpointIS()
10122 @*/
10123 PetscErrorCode DMPlexCreateCoarsePointIS(DM dm, IS *fpointIS)
10124 {
10125   CellRefiner    cellRefiner;
10126   PetscInt      *depthSize, *fpoints;
10127   PetscInt       cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
10128   PetscInt       depth, pStart, pEnd, p, vStart, vEnd, v;
10129   PetscErrorCode ierr;
10130 
10131   PetscFunctionBegin;
10132   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
10133   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
10134   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
10135   ierr = DMPlexGetCellRefiner_Internal(dm, &cellRefiner);CHKERRQ(ierr);
10136   ierr = PetscMalloc1(depth+1, &depthSize);CHKERRQ(ierr);
10137   ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr);
10138   if (cellRefiner) {ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);}
10139   ierr = PetscMalloc1(pEnd-pStart,&fpoints);CHKERRQ(ierr);
10140   for (p = 0; p < pEnd-pStart; ++p) fpoints[p] = -1;
10141   switch (cellRefiner) {
10142   case REFINER_SIMPLEX_1D:
10143   case REFINER_SIMPLEX_2D:
10144   case REFINER_HYBRID_SIMPLEX_2D:
10145   case REFINER_HEX_2D:
10146   case REFINER_HYBRID_HEX_2D:
10147   case REFINER_SIMPLEX_3D:
10148   case REFINER_HYBRID_SIMPLEX_3D:
10149   case REFINER_HEX_3D:
10150   case REFINER_HYBRID_HEX_3D:
10151     for (v = vStart; v < vEnd; ++v) fpoints[v-pStart] = vStartNew + (v - vStart);
10152     break;
10153   default:
10154     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[cellRefiner]);
10155   }
10156   ierr = ISCreateGeneral(PETSC_COMM_SELF, pEnd-pStart, fpoints, PETSC_OWN_POINTER, fpointIS);CHKERRQ(ierr);
10157   ierr = PetscFree(depthSize);CHKERRQ(ierr);
10158   PetscFunctionReturn(0);
10159 }
10160 
10161 /*@
10162   DMPlexSetRefinementUniform - Set the flag for uniform refinement
10163 
10164   Input Parameters:
10165 + dm - The DM
10166 - refinementUniform - The flag for uniform refinement
10167 
10168   Level: developer
10169 
10170 .seealso: DMRefine(), DMPlexGetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
10171 @*/
10172 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
10173 {
10174   DM_Plex *mesh = (DM_Plex*) dm->data;
10175 
10176   PetscFunctionBegin;
10177   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10178   mesh->refinementUniform = refinementUniform;
10179   PetscFunctionReturn(0);
10180 }
10181 
10182 /*@
10183   DMPlexGetRefinementUniform - Retrieve the flag for uniform refinement
10184 
10185   Input Parameter:
10186 . dm - The DM
10187 
10188   Output Parameter:
10189 . refinementUniform - The flag for uniform refinement
10190 
10191   Level: developer
10192 
10193 .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
10194 @*/
10195 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
10196 {
10197   DM_Plex *mesh = (DM_Plex*) dm->data;
10198 
10199   PetscFunctionBegin;
10200   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10201   PetscValidPointer(refinementUniform,  2);
10202   *refinementUniform = mesh->refinementUniform;
10203   PetscFunctionReturn(0);
10204 }
10205 
10206 /*@
10207   DMPlexSetRefinementLimit - Set the maximum cell volume for refinement
10208 
10209   Input Parameters:
10210 + dm - The DM
10211 - refinementLimit - The maximum cell volume in the refined mesh
10212 
10213   Level: developer
10214 
10215 .seealso: DMRefine(), DMPlexGetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
10216 @*/
10217 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
10218 {
10219   DM_Plex *mesh = (DM_Plex*) dm->data;
10220 
10221   PetscFunctionBegin;
10222   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10223   mesh->refinementLimit = refinementLimit;
10224   PetscFunctionReturn(0);
10225 }
10226 
10227 /*@
10228   DMPlexGetRefinementLimit - Retrieve the maximum cell volume for refinement
10229 
10230   Input Parameter:
10231 . dm - The DM
10232 
10233   Output Parameter:
10234 . refinementLimit - The maximum cell volume in the refined mesh
10235 
10236   Level: developer
10237 
10238 .seealso: DMRefine(), DMPlexSetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
10239 @*/
10240 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
10241 {
10242   DM_Plex *mesh = (DM_Plex*) dm->data;
10243 
10244   PetscFunctionBegin;
10245   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10246   PetscValidPointer(refinementLimit,  2);
10247   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
10248   *refinementLimit = mesh->refinementLimit;
10249   PetscFunctionReturn(0);
10250 }
10251 
10252 /*@
10253   DMPlexSetRefinementFunction - Set the function giving the maximum cell volume for refinement
10254 
10255   Input Parameters:
10256 + dm - The DM
10257 - refinementFunc - Function giving the maximum cell volume in the refined mesh
10258 
10259   Note: The calling sequence is refinementFunc(coords, limit)
10260 $ coords - Coordinates of the current point, usually a cell centroid
10261 $ limit  - The maximum cell volume for a cell containing this point
10262 
10263   Level: developer
10264 
10265 .seealso: DMRefine(), DMPlexGetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
10266 @*/
10267 PetscErrorCode DMPlexSetRefinementFunction(DM dm, PetscErrorCode (*refinementFunc)(const PetscReal [], PetscReal *))
10268 {
10269   DM_Plex *mesh = (DM_Plex*) dm->data;
10270 
10271   PetscFunctionBegin;
10272   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10273   mesh->refinementFunc = refinementFunc;
10274   PetscFunctionReturn(0);
10275 }
10276 
10277 /*@
10278   DMPlexGetRefinementFunction - Get the function giving the maximum cell volume for refinement
10279 
10280   Input Parameter:
10281 . dm - The DM
10282 
10283   Output Parameter:
10284 . refinementFunc - Function giving the maximum cell volume in the refined mesh
10285 
10286   Note: The calling sequence is refinementFunc(coords, limit)
10287 $ coords - Coordinates of the current point, usually a cell centroid
10288 $ limit  - The maximum cell volume for a cell containing this point
10289 
10290   Level: developer
10291 
10292 .seealso: DMRefine(), DMPlexSetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
10293 @*/
10294 PetscErrorCode DMPlexGetRefinementFunction(DM dm, PetscErrorCode (**refinementFunc)(const PetscReal [], PetscReal *))
10295 {
10296   DM_Plex *mesh = (DM_Plex*) dm->data;
10297 
10298   PetscFunctionBegin;
10299   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10300   PetscValidPointer(refinementFunc,  2);
10301   *refinementFunc = mesh->refinementFunc;
10302   PetscFunctionReturn(0);
10303 }
10304 
10305 PetscErrorCode DMPlexGetCellRefiner_Internal(DM dm, CellRefiner *cellRefiner)
10306 {
10307   PetscInt       dim, cStart, cEnd, coneSize, cMax, fMax;
10308   PetscErrorCode ierr;
10309 
10310   PetscFunctionBegin;
10311   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
10312   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
10313   if (cEnd <= cStart) {*cellRefiner = REFINER_NOOP; PetscFunctionReturn(0);}
10314   ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr);
10315   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, NULL, NULL);CHKERRQ(ierr);
10316   switch (dim) {
10317   case 1:
10318     switch (coneSize) {
10319     case 2:
10320       *cellRefiner = REFINER_SIMPLEX_1D;
10321       break;
10322     default:
10323       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %D in dimension %D for cell refiner", coneSize, dim);
10324     }
10325     break;
10326   case 2:
10327     switch (coneSize) {
10328     case 3:
10329       if (cMax >= 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_2D;
10330       else *cellRefiner = REFINER_SIMPLEX_2D;
10331       break;
10332     case 4:
10333       if (cMax >= 0 && fMax >= 0) *cellRefiner = REFINER_HYBRID_HEX_2D;
10334       else *cellRefiner = REFINER_HEX_2D;
10335       break;
10336     default:
10337       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %D in dimension %D for cell refiner", coneSize, dim);
10338     }
10339     break;
10340   case 3:
10341     switch (coneSize) {
10342     case 4:
10343       if (cMax >= 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_3D;
10344       else *cellRefiner = REFINER_SIMPLEX_3D;
10345       break;
10346     case 5:
10347       if (cMax == 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_3D;
10348       else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %D in dimension %D for cell refiner", coneSize, dim);
10349       break;
10350     case 6:
10351       if (cMax >= 0) *cellRefiner = REFINER_HYBRID_HEX_3D;
10352       else *cellRefiner = REFINER_HEX_3D;
10353       break;
10354     default:
10355       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %D in dimension %D for cell refiner", coneSize, dim);
10356     }
10357     break;
10358   default:
10359     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %D for cell refiner", dim);
10360   }
10361   PetscFunctionReturn(0);
10362 }
10363 
10364 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined)
10365 {
10366   PetscBool      isUniform;
10367   PetscErrorCode ierr;
10368 
10369   PetscFunctionBegin;
10370   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
10371   if (isUniform) {
10372     CellRefiner cellRefiner;
10373     PetscBool   localized;
10374 
10375     ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
10376     ierr = DMPlexGetCellRefiner_Internal(dm, &cellRefiner);CHKERRQ(ierr);
10377     ierr = DMPlexRefineUniform_Internal(dm, cellRefiner, dmRefined);CHKERRQ(ierr);
10378     ierr = DMPlexSetRegularRefinement(*dmRefined, PETSC_TRUE);CHKERRQ(ierr);
10379     ierr = DMCopyBoundary(dm, *dmRefined);CHKERRQ(ierr);
10380     if (localized) {ierr = DMLocalizeCoordinates(*dmRefined);CHKERRQ(ierr);}
10381   } else {
10382     ierr = DMPlexRefine_Internal(dm, NULL, dmRefined);CHKERRQ(ierr);
10383   }
10384   PetscFunctionReturn(0);
10385 }
10386 
10387 PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM dmRefined[])
10388 {
10389   DM             cdm = dm;
10390   PetscInt       r;
10391   PetscBool      isUniform, localized;
10392   PetscErrorCode ierr;
10393 
10394   PetscFunctionBegin;
10395   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
10396   ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
10397   if (isUniform) {
10398     for (r = 0; r < nlevels; ++r) {
10399       CellRefiner cellRefiner;
10400 
10401       ierr = DMPlexGetCellRefiner_Internal(cdm, &cellRefiner);CHKERRQ(ierr);
10402       ierr = DMPlexRefineUniform_Internal(cdm, cellRefiner, &dmRefined[r]);CHKERRQ(ierr);
10403       ierr = DMSetCoarsenLevel(dmRefined[r], cdm->leveldown);CHKERRQ(ierr);
10404       ierr = DMSetRefineLevel(dmRefined[r], cdm->levelup+1);CHKERRQ(ierr);
10405       ierr = DMCopyBoundary(cdm, dmRefined[r]);CHKERRQ(ierr);
10406       if (localized) {ierr = DMLocalizeCoordinates(dmRefined[r]);CHKERRQ(ierr);}
10407       ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr);
10408       ierr = DMPlexSetRegularRefinement(dmRefined[r], PETSC_TRUE);CHKERRQ(ierr);
10409       cdm  = dmRefined[r];
10410     }
10411   } else {
10412     for (r = 0; r < nlevels; ++r) {
10413       ierr = DMRefine(cdm, PetscObjectComm((PetscObject) dm), &dmRefined[r]);CHKERRQ(ierr);
10414       ierr = DMCopyBoundary(cdm, dmRefined[r]);CHKERRQ(ierr);
10415       if (localized) {ierr = DMLocalizeCoordinates(dmRefined[r]);CHKERRQ(ierr);}
10416       ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr);
10417       cdm  = dmRefined[r];
10418     }
10419   }
10420   PetscFunctionReturn(0);
10421 }
10422