xref: /petsc/src/dm/impls/plex/plexrefine.c (revision 149f48fdb98b7b5c0dbe27ead462caa306989693)
1 #include <petsc-private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2 #include <petscsf.h>
3 
4 #undef __FUNCT__
5 #define __FUNCT__ "GetDepthStart_Private"
6 PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart)
7 {
8   PetscFunctionBegin;
9   if (cStart) *cStart = 0;
10   if (vStart) *vStart = depthSize[depth];
11   if (fStart) *fStart = depthSize[depth] + depthSize[0];
12   if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1];
13   PetscFunctionReturn(0);
14 }
15 
16 #undef __FUNCT__
17 #define __FUNCT__ "GetDepthEnd_Private"
18 PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd)
19 {
20   PetscFunctionBegin;
21   if (cEnd) *cEnd = depthSize[depth];
22   if (vEnd) *vEnd = depthSize[depth] + depthSize[0];
23   if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1];
24   if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1];
25   PetscFunctionReturn(0);
26 }
27 
28 #undef __FUNCT__
29 #define __FUNCT__ "CellRefinerGetSizes"
30 static PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[])
31 {
32   PetscInt       cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax;
33   PetscErrorCode ierr;
34 
35   PetscFunctionBegin;
36   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
37   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
38   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
39   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
40   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
41   switch (refiner) {
42   case 0:
43     break;
44   case 1:
45     /* Simplicial 2D */
46     depthSize[0] = vEnd - vStart + fEnd - fStart;         /* Add a vertex on every face */
47     depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */
48     depthSize[2] = 4*(cEnd - cStart);                     /* Every cell split into 4 cells */
49     break;
50   case 3:
51     /* Hybrid Simplicial 2D */
52     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
53     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
54     depthSize[0] = vEnd - vStart + fMax - fStart;                                         /* Add a vertex on every face, but not hybrid faces */
55     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 */
56     depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax);                                   /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */
57     break;
58   case 2:
59     /* Hex 2D */
60     depthSize[0] = vEnd - vStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every face and cell */
61     depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart);         /* Every face is split into 2 faces and 4 faces are added for each cell */
62     depthSize[2] = 4*(cEnd - cStart);                             /* Every cell split into 4 cells */
63     break;
64   case 5:
65     /* Simplicial 3D */
66     depthSize[0] =    vEnd - vStart  +    eEnd - eStart;                    /* Add a vertex on every edge */
67     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 */
68     depthSize[2] = 4*(fEnd - fStart) + 8*(cEnd - cStart);                   /* Every face split into 4 faces and 8 faces are added for each cell */
69     depthSize[3] = 8*(cEnd - cStart);                                       /* Every cell split into 8 cells */
70     break;
71   case 7:
72     /* Hybrid Simplicial 3D */
73     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
74     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
75     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
76     /* Tetrahedra */
77     depthSize[0]  =    vEnd - vStart  +    eMax - eStart;                    /* Add a vertex on every interior edge */
78     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 */
79     depthSize[2]  = 4*(fMax - fStart) + 8*(cMax - cStart);                   /* Every interior face split into 4 faces, 8 faces added for each interior cell */
80     depthSize[3]  = 8*(cMax - cStart);                                       /* Every interior cell split into 8 cells */
81     /* Triangular Prisms */
82     depthSize[0] += 0;                                                       /* No hybrid vertices */
83     depthSize[1] +=   (eEnd - eMax)   +   (fEnd - fMax);                     /* Every hybrid edge remains, 1 edge for every hybrid face */
84     depthSize[2] += 2*(fEnd - fMax)   + 3*(cEnd - cMax);                     /* Every hybrid face split into 2 faces and 3 faces are added for each hybrid cell */
85     depthSize[3] += 4*(cEnd - cMax);                                         /* Every hybrid cell split into 4 cells */
86     break;
87   case 6:
88     /* Hex 3D */
89     depthSize[0] = vEnd - vStart + eEnd - eStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every edge, face and cell */
90     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 */
91     depthSize[2] = 4*(fEnd - fStart) + 12*(cEnd - cStart);                        /* Every face is split into 4 faces, and 12 faces are added for each cell */
92     depthSize[3] = 8*(cEnd - cStart);                                             /* Every cell split into 8 cells */
93     break;
94   case 8:
95     /* Hybrid Hex 3D */
96     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
97     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
98     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
99     /* Hexahedra */
100     depthSize[0] = vEnd - vStart + eMax - eStart + fMax - fStart + cMax - cStart; /* Add a vertex on every edge, face and cell */
101     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 */
102     depthSize[2] = 4*(fMax - fStart) + 12*(cMax - cStart);                        /* Every face is split into 4 faces, and 12 faces are added for each cell */
103     depthSize[3] = 8*(cMax - cStart);                                             /* Every cell split into 8 cells */
104     /* Quadrilateral Prisms */
105     depthSize[0] += 0;                                                            /* No hybrid vertices */
106     depthSize[1] +=   (eEnd - eMax)   +   (fEnd - fMax)   +   (cEnd - cMax);      /* Every hybrid edge remains, 1 edge for every hybrid face and hybrid cell */
107     depthSize[2] += 2*(fEnd - fMax)   + 4*(cEnd - cMax);                          /* Every hybrid face split into 2 faces and 4 faces are added for each hybrid cell */
108     depthSize[3] += 4*(cEnd - cMax);                                              /* Every hybrid cell split into 4 cells */
109     break;
110   default:
111     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
112   }
113   PetscFunctionReturn(0);
114 }
115 
116 /* Return triangle edge for orientation o, if it is r for o == 0 */
117 PETSC_STATIC_INLINE PetscInt GetTriEdge_Static(PetscInt o, PetscInt r) {
118   return (o < 0 ? 2-(o+r) : o+r)%3;
119 }
120 PETSC_STATIC_INLINE PetscInt GetTriEdgeInverse_Static(PetscInt o, PetscInt s) {
121   return (o < 0 ? 2-(o+s) : 3+s-o)%3;
122 }
123 
124 /* Return triangle subface for orientation o, if it is r for o == 0 */
125 PETSC_STATIC_INLINE PetscInt GetTriSubface_Static(PetscInt o, PetscInt r) {
126   return (o < 0 ? 3-(o+r) : o+r)%3;
127 }
128 PETSC_STATIC_INLINE PetscInt GetTriSubfaceInverse_Static(PetscInt o, PetscInt s) {
129   return (o < 0 ? 3-(o+s) : 3+s-o)%3;
130 }
131 
132 /* I HAVE NO IDEA: Return ??? for orientation o, if it is r for o == 0 */
133 PETSC_STATIC_INLINE PetscInt GetTetSomething_Static(PetscInt o, PetscInt r) {
134   return (o < 0 ? 1-(o+r) : o+r)%3;
135 }
136 PETSC_STATIC_INLINE PetscInt GetTetSomethingInverse_Static(PetscInt o, PetscInt s) {
137   return (o < 0 ? 1-(o+s) : 3+s-o)%3;
138 }
139 
140 
141 /* Return quad edge for orientation o, if it is r for o == 0 */
142 PETSC_STATIC_INLINE PetscInt GetQuadEdge_Static(PetscInt o, PetscInt r) {
143   return (o < 0 ? 3-(o+r) : o+r)%4;
144 }
145 PETSC_STATIC_INLINE PetscInt GetQuadEdgeInverse_Static(PetscInt o, PetscInt s) {
146   return (o < 0 ? 3-(o+s) : 4+s-o)%4;
147 }
148 
149 /* Return quad subface for orientation o, if it is r for o == 0 */
150 PETSC_STATIC_INLINE PetscInt GetQuadSubface_Static(PetscInt o, PetscInt r) {
151   return (o < 0 ? 4-(o+r) : o+r)%4;
152 }
153 PETSC_STATIC_INLINE PetscInt GetQuadSubfaceInverse_Static(PetscInt o, PetscInt s) {
154   return (o < 0 ? 4-(o+s) : 4+s-o)%4;
155 }
156 
157 #undef __FUNCT__
158 #define __FUNCT__ "CellRefinerSetConeSizes"
159 static PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
160 {
161   PetscInt       depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, e, r;
162   PetscErrorCode ierr;
163 
164   PetscFunctionBegin;
165   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
166   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
167   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
168   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
169   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
170   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
171   if (refiner) {ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);}
172   switch (refiner) {
173   case 0: break;
174   case 1:
175     /* Simplicial 2D */
176     /* All cells have 3 faces */
177     for (c = cStart; c < cEnd; ++c) {
178       for (r = 0; r < 4; ++r) {
179         const PetscInt newp = (c - cStart)*4 + r;
180 
181         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
182       }
183     }
184     /* Split faces have 2 vertices and the same cells as the parent */
185     for (f = fStart; f < fEnd; ++f) {
186       for (r = 0; r < 2; ++r) {
187         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
188         PetscInt       size;
189 
190         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
191         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
192         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
193       }
194     }
195     /* Interior faces have 2 vertices and 2 cells */
196     for (c = cStart; c < cEnd; ++c) {
197       for (r = 0; r < 3; ++r) {
198         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
199 
200         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
201         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
202       }
203     }
204     /* Old vertices have identical supports */
205     for (v = vStart; v < vEnd; ++v) {
206       const PetscInt newp = vStartNew + (v - vStart);
207       PetscInt       size;
208 
209       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
210       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
211     }
212     /* Face vertices have 2 + cells*2 supports */
213     for (f = fStart; f < fEnd; ++f) {
214       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
215       PetscInt       size;
216 
217       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
218       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr);
219     }
220     break;
221   case 2:
222     /* Hex 2D */
223     /* All cells have 4 faces */
224     for (c = cStart; c < cEnd; ++c) {
225       for (r = 0; r < 4; ++r) {
226         const PetscInt newp = cStartNew + (c - cStart)*4 + r;
227 
228         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
229       }
230     }
231     /* Split faces have 2 vertices and the same cells as the parent */
232     for (f = fStart; f < fEnd; ++f) {
233       for (r = 0; r < 2; ++r) {
234         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
235         PetscInt       size;
236 
237         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
238         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
239         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
240       }
241     }
242     /* Interior faces have 2 vertices and 2 cells */
243     for (c = cStart; c < cEnd; ++c) {
244       for (r = 0; r < 4; ++r) {
245         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
246 
247         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
248         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
249       }
250     }
251     /* Old vertices have identical supports */
252     for (v = vStart; v < vEnd; ++v) {
253       const PetscInt newp = vStartNew + (v - vStart);
254       PetscInt       size;
255 
256       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
257       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
258     }
259     /* Face vertices have 2 + cells supports */
260     for (f = fStart; f < fEnd; ++f) {
261       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
262       PetscInt       size;
263 
264       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
265       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
266     }
267     /* Cell vertices have 4 supports */
268     for (c = cStart; c < cEnd; ++c) {
269       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
270 
271       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
272     }
273     break;
274   case 3:
275     /* Hybrid Simplicial 2D */
276     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
277     cMax = PetscMin(cEnd, cMax);
278     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
279     fMax = PetscMin(fEnd, fMax);
280     ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
281     /* Interior cells have 3 faces */
282     for (c = cStart; c < cMax; ++c) {
283       for (r = 0; r < 4; ++r) {
284         const PetscInt newp = cStartNew + (c - cStart)*4 + r;
285 
286         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
287       }
288     }
289     /* Hybrid cells have 4 faces */
290     for (c = cMax; c < cEnd; ++c) {
291       for (r = 0; r < 2; ++r) {
292         const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
293 
294         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
295       }
296     }
297     /* Interior split faces have 2 vertices and the same cells as the parent */
298     for (f = fStart; f < fMax; ++f) {
299       for (r = 0; r < 2; ++r) {
300         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
301         PetscInt       size;
302 
303         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
304         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
305         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
306       }
307     }
308     /* Interior cell faces have 2 vertices and 2 cells */
309     for (c = cStart; c < cMax; ++c) {
310       for (r = 0; r < 3; ++r) {
311         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
312 
313         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
314         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
315       }
316     }
317     /* Hybrid faces have 2 vertices and the same cells */
318     for (f = fMax; f < fEnd; ++f) {
319       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
320       PetscInt       size;
321 
322       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
323       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
324       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
325     }
326     /* Hybrid cell faces have 2 vertices and 2 cells */
327     for (c = cMax; c < cEnd; ++c) {
328       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
329 
330       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
331       ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
332     }
333     /* Old vertices have identical supports */
334     for (v = vStart; v < vEnd; ++v) {
335       const PetscInt newp = vStartNew + (v - vStart);
336       PetscInt       size;
337 
338       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
339       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
340     }
341     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
342     for (f = fStart; f < fMax; ++f) {
343       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
344       const PetscInt *support;
345       PetscInt       size, newSize = 2, s;
346 
347       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
348       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
349       for (s = 0; s < size; ++s) {
350         if (support[s] >= cMax) newSize += 1;
351         else newSize += 2;
352       }
353       ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr);
354     }
355     break;
356   case 5:
357     /* Simplicial 3D */
358     /* All cells have 4 faces */
359     for (c = cStart; c < cEnd; ++c) {
360       for (r = 0; r < 8; ++r) {
361         const PetscInt newp = cStartNew + (c - cStart)*8 + r;
362 
363         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
364       }
365     }
366     /* Split faces have 3 edges and the same cells as the parent */
367     for (f = fStart; f < fEnd; ++f) {
368       for (r = 0; r < 4; ++r) {
369         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
370         PetscInt       size;
371 
372         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
373         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
374         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
375       }
376     }
377     /* Interior cell faces have 3 edges and 2 cells */
378     for (c = cStart; c < cEnd; ++c) {
379       for (r = 0; r < 8; ++r) {
380         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + r;
381 
382         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
383         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
384       }
385     }
386     /* Split edges have 2 vertices and the same faces */
387     for (e = eStart; e < eEnd; ++e) {
388       for (r = 0; r < 2; ++r) {
389         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
390         PetscInt       size;
391 
392         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
393         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
394         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
395       }
396     }
397     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
398     for (f = fStart; f < fEnd; ++f) {
399       for (r = 0; r < 3; ++r) {
400         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
401         const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
402         PetscInt        coneSize, c, supportSize, s, er, intFaces = 0;
403 
404         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
405         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
406         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
407         for (s = 0; s < supportSize; ++s) {
408           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
409           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
410           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
411           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
412           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
413           er = GetTetSomethingInverse_Static(ornt[c], r);
414           if (er == eint[c]) {
415             intFaces += 1;
416           } else {
417             intFaces += 2;
418           }
419         }
420         ierr = DMPlexSetSupportSize(rdm, newp, 2+intFaces);CHKERRQ(ierr);
421       }
422     }
423     /* Interior cell edges have 2 vertices and 4 faces */
424     for (c = cStart; c < cEnd; ++c) {
425       const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
426 
427       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
428       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
429     }
430     /* Old vertices have identical supports */
431     for (v = vStart; v < vEnd; ++v) {
432       const PetscInt newp = vStartNew + (v - vStart);
433       PetscInt       size;
434 
435       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
436       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
437     }
438     /* Edge vertices have 2 + faces*2 + cells*0/1 supports */
439     for (e = eStart; e < eEnd; ++e) {
440       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
441       PetscInt       size, *star = NULL, starSize, s, cellSize = 0;
442 
443       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
444       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
445       for (s = 0; s < starSize*2; s += 2) {
446         const PetscInt *cone, *ornt;
447         PetscInt        e01, e23;
448 
449         if ((star[s] >= cStart) && (star[s] < cEnd)) {
450           /* Check edge 0-1 */
451           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
452           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
453           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
454           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
455           /* Check edge 2-3 */
456           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
457           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
458           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
459           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
460           if ((e01 == e) || (e23 == e)) ++cellSize;
461         }
462       }
463       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
464       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2 + cellSize);CHKERRQ(ierr);
465     }
466     break;
467   case 7:
468     /* Hybrid Simplicial 3D */
469     ierr = DMPlexSetHybridBounds(rdm, cStartNew + 8*(cMax-cStart), fStartNew + 4*(fMax - fStart) + 8*(cMax - cStart),
470                                  eStartNew + 2*(eMax - eStart) + 3*(fMax - fStart) + (cMax - cStart), PETSC_DETERMINE);CHKERRQ(ierr);
471     /* Interior cells have 4 faces */
472     for (c = cStart; c < cMax; ++c) {
473       for (r = 0; r < 8; ++r) {
474         const PetscInt newp = cStartNew + (c - cStart)*8 + r;
475 
476         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
477       }
478     }
479     /* Hybrid cells have 5 faces */
480     for (c = cMax; c < cEnd; ++c) {
481       for (r = 0; r < 4; ++r) {
482         const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;
483 
484         ierr = DMPlexSetConeSize(rdm, newp, 5);CHKERRQ(ierr);
485       }
486     }
487     /* Interior split faces have 3 edges and the same cells as the parent */
488     for (f = fStart; f < fMax; ++f) {
489       for (r = 0; r < 4; ++r) {
490         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
491         PetscInt       size;
492 
493         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
494         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
495         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
496       }
497     }
498     /* Interior cell faces have 3 edges and 2 cells */
499     for (c = cStart; c < cMax; ++c) {
500       for (r = 0; r < 8; ++r) {
501         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + r;
502 
503         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
504         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
505       }
506     }
507     /* Hybrid split faces have 4 edges and the same cells as the parent */
508     for (f = fMax; f < fEnd; ++f) {
509       for (r = 0; r < 2; ++r) {
510         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;
511         PetscInt       size;
512 
513         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
514         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
515         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
516       }
517     }
518     /* Hybrid cells faces have 4 edges and 2 cells */
519     for (c = cMax; c < cEnd; ++c) {
520       for (r = 0; r < 3; ++r) {
521         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + r;
522 
523         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
524         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
525       }
526     }
527     /* Interior split edges have 2 vertices and the same faces */
528     for (e = eStart; e < eMax; ++e) {
529       for (r = 0; r < 2; ++r) {
530         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
531         PetscInt       size;
532 
533         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
534         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
535         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
536       }
537     }
538     /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
539     for (f = fStart; f < fMax; ++f) {
540       for (r = 0; r < 3; ++r) {
541         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
542         const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
543         PetscInt        coneSize, c, supportSize, s, er, intFaces = 0;
544 
545         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
546         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
547         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
548         for (s = 0; s < supportSize; ++s) {
549           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
550           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
551           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
552           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
553           if (support[s] < cMax) {
554             /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
555             er = GetTetSomethingInverse_Static(ornt[c], r);
556             if (er == eint[c]) {
557               intFaces += 1;
558             } else {
559               intFaces += 2;
560             }
561           } else {
562             intFaces += 1;
563           }
564         }
565         ierr = DMPlexSetSupportSize(rdm, newp, 2+intFaces);CHKERRQ(ierr);
566       }
567     }
568     /* Interior cell edges have 2 vertices and 4 faces */
569     for (c = cStart; c < cMax; ++c) {
570       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
571 
572       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
573       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
574     }
575     /* Hybrid edges have 2 vertices and the same faces */
576     for (e = eMax; e < eEnd; ++e) {
577       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
578       PetscInt       size;
579 
580       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
581       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
582       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
583     }
584     /* Hybrid face edges have 2 vertices and 2+2*cells faces */
585     for (f = fMax; f < fEnd; ++f) {
586       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
587       PetscInt       size;
588 
589       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
590       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
591       ierr = DMPlexSetSupportSize(rdm, newp, 2+2*size);CHKERRQ(ierr);
592     }
593     /* Interior vertices have identical supports */
594     for (v = vStart; v < vEnd; ++v) {
595       const PetscInt newp = vStartNew + (v - vStart);
596       PetscInt       size;
597 
598       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
599       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
600     }
601     /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
602     for (e = eStart; e < eMax; ++e) {
603       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
604       const PetscInt *support;
605       PetscInt        size, *star = NULL, starSize, s, faceSize = 0, cellSize = 0;
606 
607       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
608       ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
609       for (s = 0; s < size; ++s) {
610         if (support[s] < fMax) faceSize += 2;
611         else                   faceSize += 1;
612       }
613       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
614       for (s = 0; s < starSize*2; s += 2) {
615         const PetscInt *cone, *ornt;
616         PetscInt        e01, e23;
617 
618         if ((star[s] >= cStart) && (star[s] < cMax)) {
619           /* Check edge 0-1 */
620           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
621           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
622           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
623           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
624           /* Check edge 2-3 */
625           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
626           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
627           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
628           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
629           if ((e01 == e) || (e23 == e)) ++cellSize;
630         }
631       }
632       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
633       ierr = DMPlexSetSupportSize(rdm, newp, 2 + faceSize + cellSize);CHKERRQ(ierr);
634     }
635     break;
636   case 6:
637     /* Hex 3D */
638     /* All cells have 6 faces */
639     for (c = cStart; c < cEnd; ++c) {
640       for (r = 0; r < 8; ++r) {
641         const PetscInt newp = (c - cStart)*8 + r;
642 
643         ierr = DMPlexSetConeSize(rdm, newp, 6);CHKERRQ(ierr);
644       }
645     }
646     /* Split faces have 4 edges and the same cells as the parent */
647     for (f = fStart; f < fEnd; ++f) {
648       for (r = 0; r < 4; ++r) {
649         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
650         PetscInt       size;
651 
652         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
653         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
654         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
655       }
656     }
657     /* Interior faces have 4 edges and 2 cells */
658     for (c = cStart; c < cEnd; ++c) {
659       for (r = 0; r < 12; ++r) {
660         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
661 
662         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
663         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
664       }
665     }
666     /* Split edges have 2 vertices and the same faces as the parent */
667     for (e = eStart; e < eEnd; ++e) {
668       for (r = 0; r < 2; ++r) {
669         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
670         PetscInt       size;
671 
672         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
673         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
674         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
675       }
676     }
677     /* Face edges have 2 vertices and 2+cells faces */
678     for (f = fStart; f < fEnd; ++f) {
679       for (r = 0; r < 4; ++r) {
680         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
681         PetscInt       size;
682 
683         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
684         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
685         ierr = DMPlexSetSupportSize(rdm, newp, 2+size);CHKERRQ(ierr);
686       }
687     }
688     /* Cell edges have 2 vertices and 4 faces */
689     for (c = cStart; c < cEnd; ++c) {
690       for (r = 0; r < 6; ++r) {
691         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
692 
693         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
694         ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
695       }
696     }
697     /* Old vertices have identical supports */
698     for (v = vStart; v < vEnd; ++v) {
699       const PetscInt newp = vStartNew + (v - vStart);
700       PetscInt       size;
701 
702       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
703       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
704     }
705     /* Edge vertices have 2 + faces supports */
706     for (e = eStart; e < eEnd; ++e) {
707       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
708       PetscInt       size;
709 
710       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
711       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
712     }
713     /* Face vertices have 4 + cells supports */
714     for (f = fStart; f < fEnd; ++f) {
715       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
716       PetscInt       size;
717 
718       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
719       ierr = DMPlexSetSupportSize(rdm, newp, 4 + size);CHKERRQ(ierr);
720     }
721     /* Cell vertices have 6 supports */
722     for (c = cStart; c < cEnd; ++c) {
723       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
724 
725       ierr = DMPlexSetSupportSize(rdm, newp, 6);CHKERRQ(ierr);
726     }
727     break;
728   case 8:
729     /* Hybrid Hex 3D */
730     ierr = DMPlexSetHybridBounds(rdm, cStartNew + 8*(cMax-cStart), fStartNew + 4*(fMax - fStart) + 12*(cMax - cStart),
731                                  eStartNew + 2*(eMax - eStart) + 4*(fMax - fStart) + 6*(cMax - cStart), PETSC_DETERMINE);CHKERRQ(ierr);
732     /* Interior cells have 6 faces */
733     for (c = cStart; c < cMax; ++c) {
734       for (r = 0; r < 8; ++r) {
735         const PetscInt newp = cStartNew + (c - cStart)*8 + r;
736 
737         ierr = DMPlexSetConeSize(rdm, newp, 6);CHKERRQ(ierr);
738       }
739     }
740     /* Hybrid cells have 6 faces */
741     for (c = cMax; c < cEnd; ++c) {
742       for (r = 0; r < 4; ++r) {
743         const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;
744 
745         ierr = DMPlexSetConeSize(rdm, newp, 6);CHKERRQ(ierr);
746       }
747     }
748     /* Interior split faces have 4 edges and the same cells as the parent */
749     for (f = fStart; f < fMax; ++f) {
750       for (r = 0; r < 4; ++r) {
751         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
752         PetscInt       size;
753 
754         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
755         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
756         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
757       }
758     }
759     /* Interior cell faces have 4 edges and 2 cells */
760     for (c = cStart; c < cMax; ++c) {
761       for (r = 0; r < 12; ++r) {
762         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + r;
763 
764         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
765         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
766       }
767     }
768     /* Hybrid split faces have 4 edges and the same cells as the parent */
769     for (f = fMax; f < fEnd; ++f) {
770       for (r = 0; r < 2; ++r) {
771         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + r;
772         PetscInt       size;
773 
774         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
775         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
776         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
777       }
778     }
779     /* Hybrid cells faces have 4 edges and 2 cells */
780     for (c = cMax; c < cEnd; ++c) {
781       for (r = 0; r < 4; ++r) {
782         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + r;
783 
784         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
785         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
786       }
787     }
788     /* Interior split edges have 2 vertices and the same faces as the parent */
789     for (e = eStart; e < eMax; ++e) {
790       for (r = 0; r < 2; ++r) {
791         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
792         PetscInt       size;
793 
794         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
795         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
796         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
797       }
798     }
799     /* Interior face edges have 2 vertices and 2+cells faces */
800     for (f = fStart; f < fMax; ++f) {
801       for (r = 0; r < 4; ++r) {
802         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
803         PetscInt       size;
804 
805         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
806         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
807         ierr = DMPlexSetSupportSize(rdm, newp, 2+size);CHKERRQ(ierr);
808       }
809     }
810     /* Interior cell edges have 2 vertices and 4 faces */
811     for (c = cStart; c < cMax; ++c) {
812       for (r = 0; r < 6; ++r) {
813         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
814 
815         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
816         ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
817       }
818     }
819     /* Hybrid edges have 2 vertices and the same faces */
820     for (e = eMax; e < eEnd; ++e) {
821       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (e - eMax);
822       PetscInt       size;
823 
824       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
825       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
826       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
827     }
828     /* Hybrid face edges have 2 vertices and 2+cells faces */
829     for (f = fMax; f < fEnd; ++f) {
830       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
831       PetscInt       size;
832 
833       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
834       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
835       ierr = DMPlexSetSupportSize(rdm, newp, 2+size);CHKERRQ(ierr);
836     }
837     /* Hybrid cell edges have 2 vertices and 4 faces */
838     for (c = cMax; c < cEnd; ++c) {
839       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
840 
841       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
842       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
843     }
844     /* Interior vertices have identical supports */
845     for (v = vStart; v < vEnd; ++v) {
846       const PetscInt newp = vStartNew + (v - vStart);
847       PetscInt       size;
848 
849       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
850       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
851     }
852     /* Interior edge vertices have 2 + faces supports */
853     for (e = eStart; e < eMax; ++e) {
854       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
855       PetscInt       size;
856 
857       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
858       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
859     }
860     /* Interior face vertices have 4 + cells supports */
861     for (f = fStart; f < fMax; ++f) {
862       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
863       PetscInt       size;
864 
865       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
866       ierr = DMPlexSetSupportSize(rdm, newp, 4 + size);CHKERRQ(ierr);
867     }
868     /* Interior cell vertices have 6 supports */
869     for (c = cStart; c < cMax; ++c) {
870       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
871 
872       ierr = DMPlexSetSupportSize(rdm, newp, 6);CHKERRQ(ierr);
873     }
874     break;
875   default:
876     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
877   }
878   PetscFunctionReturn(0);
879 }
880 
881 #undef __FUNCT__
882 #define __FUNCT__ "CellRefinerSetCones"
883 static PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
884 {
885   const PetscInt *faces, cellInd[4] = {0, 1, 2, 3};
886   PetscInt        cStart,    cEnd,    cMax,    vStart,    vEnd, vMax, fStart,    fEnd,    fMax,    eStart,    eEnd,    eMax;
887   PetscInt        cStartNew, cEndNew, cMaxNew, vStartNew, vEndNew,    fStartNew, fEndNew, fMaxNew, eStartNew, eEndNew, eMaxNew;
888   PetscInt        depth, maxSupportSize, *supportRef, c, f, e, v, r, p;
889   PetscErrorCode  ierr;
890 
891   PetscFunctionBegin;
892   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
893   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
894   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
895   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
896   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
897   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
898   if (refiner) {
899     ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
900     ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr);
901   }
902   switch (refiner) {
903   case 0: break;
904   case 1:
905     /* Simplicial 2D */
906     /*
907      2
908      |\
909      | \
910      |  \
911      |   \
912      | C  \
913      |     \
914      |      \
915      2---1---1
916      |\  D  / \
917      | 2   0   \
918      |A \ /  B  \
919      0---0-------1
920      */
921     /* All cells have 3 faces */
922     for (c = cStart; c < cEnd; ++c) {
923       const PetscInt  newp = cStartNew + (c - cStart)*4;
924       const PetscInt *cone, *ornt;
925       PetscInt        coneNew[3], orntNew[3];
926 
927       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
928       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
929       /* A triangle */
930       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
931       orntNew[0] = ornt[0];
932       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
933       orntNew[1] = -2;
934       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
935       orntNew[2] = ornt[2];
936       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
937       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
938 #if 1
939       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
940       for (p = 0; p < 3; ++p) {
941         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
942       }
943 #endif
944       /* B triangle */
945       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
946       orntNew[0] = ornt[0];
947       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
948       orntNew[1] = ornt[1];
949       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
950       orntNew[2] = -2;
951       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
952       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
953 #if 1
954       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
955       for (p = 0; p < 3; ++p) {
956         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
957       }
958 #endif
959       /* C triangle */
960       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
961       orntNew[0] = -2;
962       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
963       orntNew[1] = ornt[1];
964       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
965       orntNew[2] = ornt[2];
966       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
967       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
968 #if 1
969       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
970       for (p = 0; p < 3; ++p) {
971         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
972       }
973 #endif
974       /* D triangle */
975       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
976       orntNew[0] = 0;
977       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
978       orntNew[1] = 0;
979       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
980       orntNew[2] = 0;
981       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
982       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
983 #if 1
984       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
985       for (p = 0; p < 3; ++p) {
986         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
987       }
988 #endif
989     }
990     /* Split faces have 2 vertices and the same cells as the parent */
991     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
992     ierr = PetscMalloc1((2 + maxSupportSize*2), &supportRef);CHKERRQ(ierr);
993     for (f = fStart; f < fEnd; ++f) {
994       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
995 
996       for (r = 0; r < 2; ++r) {
997         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
998         const PetscInt *cone, *ornt, *support;
999         PetscInt        coneNew[2], coneSize, c, supportSize, s;
1000 
1001         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1002         coneNew[0]       = vStartNew + (cone[0] - vStart);
1003         coneNew[1]       = vStartNew + (cone[1] - vStart);
1004         coneNew[(r+1)%2] = newv;
1005         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1006 #if 1
1007         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1008         for (p = 0; p < 2; ++p) {
1009           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1010         }
1011 #endif
1012         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1013         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1014         for (s = 0; s < supportSize; ++s) {
1015           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1016           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1017           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1018           for (c = 0; c < coneSize; ++c) {
1019             if (cone[c] == f) break;
1020           }
1021           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
1022         }
1023         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1024 #if 1
1025         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1026         for (p = 0; p < supportSize; ++p) {
1027           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
1028         }
1029 #endif
1030       }
1031     }
1032     /* Interior faces have 2 vertices and 2 cells */
1033     for (c = cStart; c < cEnd; ++c) {
1034       const PetscInt *cone;
1035 
1036       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1037       for (r = 0; r < 3; ++r) {
1038         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
1039         PetscInt       coneNew[2];
1040         PetscInt       supportNew[2];
1041 
1042         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
1043         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
1044         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1045 #if 1
1046         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1047         for (p = 0; p < 2; ++p) {
1048           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1049         }
1050 #endif
1051         supportNew[0] = (c - cStart)*4 + (r+1)%3;
1052         supportNew[1] = (c - cStart)*4 + 3;
1053         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1054 #if 1
1055         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1056         for (p = 0; p < 2; ++p) {
1057           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1058         }
1059 #endif
1060       }
1061     }
1062     /* Old vertices have identical supports */
1063     for (v = vStart; v < vEnd; ++v) {
1064       const PetscInt  newp = vStartNew + (v - vStart);
1065       const PetscInt *support, *cone;
1066       PetscInt        size, s;
1067 
1068       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
1069       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
1070       for (s = 0; s < size; ++s) {
1071         PetscInt r = 0;
1072 
1073         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1074         if (cone[1] == v) r = 1;
1075         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1076       }
1077       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1078 #if 1
1079       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1080       for (p = 0; p < size; ++p) {
1081         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
1082       }
1083 #endif
1084     }
1085     /* Face vertices have 2 + cells*2 supports */
1086     for (f = fStart; f < fEnd; ++f) {
1087       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
1088       const PetscInt *cone, *support;
1089       PetscInt        size, s;
1090 
1091       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1092       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1093       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1094       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1095       for (s = 0; s < size; ++s) {
1096         PetscInt r = 0;
1097 
1098         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1099         if      (cone[1] == f) r = 1;
1100         else if (cone[2] == f) r = 2;
1101         supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
1102         supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
1103       }
1104       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1105 #if 1
1106       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1107       for (p = 0; p < 2+size*2; ++p) {
1108         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
1109       }
1110 #endif
1111     }
1112     ierr = PetscFree(supportRef);CHKERRQ(ierr);
1113     break;
1114   case 2:
1115     /* Hex 2D */
1116     /*
1117      3---------2---------2
1118      |         |         |
1119      |    D    2    C    |
1120      |         |         |
1121      3----3----0----1----1
1122      |         |         |
1123      |    A    0    B    |
1124      |         |         |
1125      0---------0---------1
1126      */
1127     /* All cells have 4 faces */
1128     for (c = cStart; c < cEnd; ++c) {
1129       const PetscInt  newp = (c - cStart)*4;
1130       const PetscInt *cone, *ornt;
1131       PetscInt        coneNew[4], orntNew[4];
1132 
1133       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1134       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1135       /* A quad */
1136       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1137       orntNew[0] = ornt[0];
1138       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
1139       orntNew[1] = 0;
1140       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
1141       orntNew[2] = -2;
1142       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
1143       orntNew[3] = ornt[3];
1144       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1145       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1146 #if 1
1147       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
1148       for (p = 0; p < 4; ++p) {
1149         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1150       }
1151 #endif
1152       /* B quad */
1153       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1154       orntNew[0] = ornt[0];
1155       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1156       orntNew[1] = ornt[1];
1157       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
1158       orntNew[2] = 0;
1159       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
1160       orntNew[3] = -2;
1161       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1162       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1163 #if 1
1164       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
1165       for (p = 0; p < 4; ++p) {
1166         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1167       }
1168 #endif
1169       /* C quad */
1170       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
1171       orntNew[0] = -2;
1172       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1173       orntNew[1] = ornt[1];
1174       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1175       orntNew[2] = ornt[2];
1176       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
1177       orntNew[3] = 0;
1178       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1179       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1180 #if 1
1181       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
1182       for (p = 0; p < 4; ++p) {
1183         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1184       }
1185 #endif
1186       /* D quad */
1187       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
1188       orntNew[0] = 0;
1189       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
1190       orntNew[1] = -2;
1191       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1192       orntNew[2] = ornt[2];
1193       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
1194       orntNew[3] = ornt[3];
1195       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
1196       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
1197 #if 1
1198       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
1199       for (p = 0; p < 4; ++p) {
1200         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1201       }
1202 #endif
1203     }
1204     /* Split faces have 2 vertices and the same cells as the parent */
1205     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
1206     ierr = PetscMalloc1((2 + maxSupportSize*2), &supportRef);CHKERRQ(ierr);
1207     for (f = fStart; f < fEnd; ++f) {
1208       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
1209 
1210       for (r = 0; r < 2; ++r) {
1211         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
1212         const PetscInt *cone, *ornt, *support;
1213         PetscInt        coneNew[2], coneSize, c, supportSize, s;
1214 
1215         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1216         coneNew[0]       = vStartNew + (cone[0] - vStart);
1217         coneNew[1]       = vStartNew + (cone[1] - vStart);
1218         coneNew[(r+1)%2] = newv;
1219         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1220 #if 1
1221         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1222         for (p = 0; p < 2; ++p) {
1223           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1224         }
1225 #endif
1226         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1227         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1228         for (s = 0; s < supportSize; ++s) {
1229           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1230           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1231           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1232           for (c = 0; c < coneSize; ++c) {
1233             if (cone[c] == f) break;
1234           }
1235           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
1236         }
1237         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1238 #if 1
1239         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1240         for (p = 0; p < supportSize; ++p) {
1241           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
1242         }
1243 #endif
1244       }
1245     }
1246     /* Interior faces have 2 vertices and 2 cells */
1247     for (c = cStart; c < cEnd; ++c) {
1248       const PetscInt *cone;
1249       PetscInt        coneNew[2], supportNew[2];
1250 
1251       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1252       for (r = 0; r < 4; ++r) {
1253         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
1254 
1255         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
1256         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
1257         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1258 #if 1
1259         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1260         for (p = 0; p < 2; ++p) {
1261           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1262         }
1263 #endif
1264         supportNew[0] = (c - cStart)*4 + r;
1265         supportNew[1] = (c - cStart)*4 + (r+1)%4;
1266         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1267 #if 1
1268         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1269         for (p = 0; p < 2; ++p) {
1270           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1271         }
1272 #endif
1273       }
1274     }
1275     /* Old vertices have identical supports */
1276     for (v = vStart; v < vEnd; ++v) {
1277       const PetscInt  newp = vStartNew + (v - vStart);
1278       const PetscInt *support, *cone;
1279       PetscInt        size, s;
1280 
1281       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
1282       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
1283       for (s = 0; s < size; ++s) {
1284         PetscInt r = 0;
1285 
1286         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1287         if (cone[1] == v) r = 1;
1288         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1289       }
1290       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1291 #if 1
1292       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1293       for (p = 0; p < size; ++p) {
1294         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
1295       }
1296 #endif
1297     }
1298     /* Face vertices have 2 + cells supports */
1299     for (f = fStart; f < fEnd; ++f) {
1300       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
1301       const PetscInt *cone, *support;
1302       PetscInt        size, s;
1303 
1304       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1305       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1306       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1307       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1308       for (s = 0; s < size; ++s) {
1309         PetscInt r = 0;
1310 
1311         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1312         if      (cone[1] == f) r = 1;
1313         else if (cone[2] == f) r = 2;
1314         else if (cone[3] == f) r = 3;
1315         supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r;
1316       }
1317       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1318 #if 1
1319       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1320       for (p = 0; p < 2+size; ++p) {
1321         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
1322       }
1323 #endif
1324     }
1325     /* Cell vertices have 4 supports */
1326     for (c = cStart; c < cEnd; ++c) {
1327       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
1328       PetscInt       supportNew[4];
1329 
1330       for (r = 0; r < 4; ++r) {
1331         supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
1332       }
1333       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1334     }
1335     ierr = PetscFree(supportRef);CHKERRQ(ierr);
1336     break;
1337   case 3:
1338     /* Hybrid Simplicial 2D */
1339     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
1340     cMax = PetscMin(cEnd, cMax);
1341     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
1342     fMax = PetscMin(fEnd, fMax);
1343     ierr = DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, NULL, NULL);CHKERRQ(ierr);
1344     /* Interior cells have 3 faces */
1345     for (c = cStart; c < cMax; ++c) {
1346       const PetscInt  newp = cStartNew + (c - cStart)*4;
1347       const PetscInt *cone, *ornt;
1348       PetscInt        coneNew[3], orntNew[3];
1349 
1350       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1351       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1352       /* A triangle */
1353       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1354       orntNew[0] = ornt[0];
1355       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
1356       orntNew[1] = -2;
1357       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1358       orntNew[2] = ornt[2];
1359       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1360       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1361 #if 1
1362       if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior cell [%d, %d)", newp+0, cStartNew, cMaxNew);
1363       for (p = 0; p < 3; ++p) {
1364         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
1365       }
1366 #endif
1367       /* B triangle */
1368       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1369       orntNew[0] = ornt[0];
1370       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1371       orntNew[1] = ornt[1];
1372       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
1373       orntNew[2] = -2;
1374       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1375       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1376 #if 1
1377       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
1378       for (p = 0; p < 3; ++p) {
1379         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1380       }
1381 #endif
1382       /* C triangle */
1383       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
1384       orntNew[0] = -2;
1385       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1386       orntNew[1] = ornt[1];
1387       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1388       orntNew[2] = ornt[2];
1389       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1390       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1391 #if 1
1392       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
1393       for (p = 0; p < 3; ++p) {
1394         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1395       }
1396 #endif
1397       /* D triangle */
1398       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
1399       orntNew[0] = 0;
1400       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
1401       orntNew[1] = 0;
1402       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
1403       orntNew[2] = 0;
1404       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
1405       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
1406 #if 1
1407       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
1408       for (p = 0; p < 3; ++p) {
1409         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1410       }
1411 #endif
1412     }
1413     /*
1414      2----3----3
1415      |         |
1416      |    B    |
1417      |         |
1418      0----4--- 1
1419      |         |
1420      |    A    |
1421      |         |
1422      0----2----1
1423      */
1424     /* Hybrid cells have 4 faces */
1425     for (c = cMax; c < cEnd; ++c) {
1426       const PetscInt  newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
1427       const PetscInt *cone, *ornt;
1428       PetscInt        coneNew[4], orntNew[4];
1429 
1430       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1431       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1432       /* A quad */
1433       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1434       orntNew[0] = ornt[0];
1435       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1436       orntNew[1] = ornt[1];
1437       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax);
1438       orntNew[2] = 0;
1439       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
1440       orntNew[3] = 0;
1441       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1442       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1443 #if 1
1444       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
1445       for (p = 0; p < 4; ++p) {
1446         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1447       }
1448 #endif
1449       /* B quad */
1450       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1451       orntNew[0] = ornt[0];
1452       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1453       orntNew[1] = ornt[1];
1454       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
1455       orntNew[2] = 0;
1456       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax);
1457       orntNew[3] = 0;
1458       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1459       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1460 #if 1
1461       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
1462       for (p = 0; p < 4; ++p) {
1463         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1464       }
1465 #endif
1466     }
1467     /* Interior split faces have 2 vertices and the same cells as the parent */
1468     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
1469     ierr = PetscMalloc1((2 + maxSupportSize*2), &supportRef);CHKERRQ(ierr);
1470     for (f = fStart; f < fMax; ++f) {
1471       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
1472 
1473       for (r = 0; r < 2; ++r) {
1474         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
1475         const PetscInt *cone, *ornt, *support;
1476         PetscInt        coneNew[2], coneSize, c, supportSize, s;
1477 
1478         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1479         coneNew[0]       = vStartNew + (cone[0] - vStart);
1480         coneNew[1]       = vStartNew + (cone[1] - vStart);
1481         coneNew[(r+1)%2] = newv;
1482         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1483 #if 1
1484         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1485         for (p = 0; p < 2; ++p) {
1486           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1487         }
1488 #endif
1489         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1490         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1491         for (s = 0; s < supportSize; ++s) {
1492           if (support[s] >= cMax) {
1493             supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
1494           } else {
1495             ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1496             ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1497             ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1498             for (c = 0; c < coneSize; ++c) {
1499               if (cone[c] == f) break;
1500             }
1501             supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
1502           }
1503         }
1504         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1505 #if 1
1506         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1507         for (p = 0; p < supportSize; ++p) {
1508           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
1509         }
1510 #endif
1511       }
1512     }
1513     /* Interior cell faces have 2 vertices and 2 cells */
1514     for (c = cStart; c < cMax; ++c) {
1515       const PetscInt *cone;
1516 
1517       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1518       for (r = 0; r < 3; ++r) {
1519         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
1520         PetscInt       coneNew[2];
1521         PetscInt       supportNew[2];
1522 
1523         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
1524         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
1525         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1526 #if 1
1527         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1528         for (p = 0; p < 2; ++p) {
1529           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1530         }
1531 #endif
1532         supportNew[0] = (c - cStart)*4 + (r+1)%3;
1533         supportNew[1] = (c - cStart)*4 + 3;
1534         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1535 #if 1
1536         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1537         for (p = 0; p < 2; ++p) {
1538           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1539         }
1540 #endif
1541       }
1542     }
1543     /* Interior hybrid faces have 2 vertices and the same cells */
1544     for (f = fMax; f < fEnd; ++f) {
1545       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
1546       const PetscInt *cone;
1547       const PetscInt *support;
1548       PetscInt        coneNew[2];
1549       PetscInt        supportNew[2];
1550       PetscInt        size, s, r;
1551 
1552       ierr       = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1553       coneNew[0] = vStartNew + (cone[0] - vStart);
1554       coneNew[1] = vStartNew + (cone[1] - vStart);
1555       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1556 #if 1
1557       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1558       for (p = 0; p < 2; ++p) {
1559         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1560       }
1561 #endif
1562       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1563       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1564       for (s = 0; s < size; ++s) {
1565         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1566         for (r = 0; r < 2; ++r) {
1567           if (cone[r+2] == f) break;
1568         }
1569         supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
1570       }
1571       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1572 #if 1
1573       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1574       for (p = 0; p < size; ++p) {
1575         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1576       }
1577 #endif
1578     }
1579     /* Cell hybrid faces have 2 vertices and 2 cells */
1580     for (c = cMax; c < cEnd; ++c) {
1581       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
1582       const PetscInt *cone;
1583       PetscInt        coneNew[2];
1584       PetscInt        supportNew[2];
1585 
1586       ierr       = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1587       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
1588       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
1589       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1590 #if 1
1591       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1592       for (p = 0; p < 2; ++p) {
1593         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1594       }
1595 #endif
1596       supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
1597       supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
1598       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1599 #if 1
1600       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1601       for (p = 0; p < 2; ++p) {
1602         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1603       }
1604 #endif
1605     }
1606     /* Old vertices have identical supports */
1607     for (v = vStart; v < vEnd; ++v) {
1608       const PetscInt  newp = vStartNew + (v - vStart);
1609       const PetscInt *support, *cone;
1610       PetscInt        size, s;
1611 
1612       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
1613       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
1614       for (s = 0; s < size; ++s) {
1615         if (support[s] >= fMax) {
1616           supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax);
1617         } else {
1618           PetscInt r = 0;
1619 
1620           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1621           if (cone[1] == v) r = 1;
1622           supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1623         }
1624       }
1625       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1626 #if 1
1627       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1628       for (p = 0; p < size; ++p) {
1629         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
1630       }
1631 #endif
1632     }
1633     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
1634     for (f = fStart; f < fMax; ++f) {
1635       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
1636       const PetscInt *cone, *support;
1637       PetscInt        size, newSize = 2, s;
1638 
1639       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1640       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1641       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1642       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1643       for (s = 0; s < size; ++s) {
1644         PetscInt r = 0;
1645 
1646         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1647         if (support[s] >= cMax) {
1648           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax);
1649 
1650           newSize += 1;
1651         } else {
1652           if      (cone[1] == f) r = 1;
1653           else if (cone[2] == f) r = 2;
1654           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
1655           supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r;
1656 
1657           newSize += 2;
1658         }
1659       }
1660       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1661 #if 1
1662       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1663       for (p = 0; p < newSize; ++p) {
1664         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
1665       }
1666 #endif
1667     }
1668     ierr = PetscFree(supportRef);CHKERRQ(ierr);
1669     break;
1670   case 5:
1671     /* Simplicial 3D */
1672     /* All cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
1673     ierr = DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);CHKERRQ(ierr);
1674     for (c = cStart; c < cEnd; ++c) {
1675       const PetscInt  newp = cStartNew + (c - cStart)*8;
1676       const PetscInt *cone, *ornt;
1677       PetscInt        coneNew[4], orntNew[4];
1678 
1679       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1680       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1681       /* A tetrahedron: {0, a, c, d} */
1682       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
1683       orntNew[0] = ornt[0];
1684       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
1685       orntNew[1] = ornt[1];
1686       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
1687       orntNew[2] = ornt[2];
1688       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
1689       orntNew[3] = 0;
1690       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1691       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1692 #if 1
1693       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
1694       for (p = 0; p < 4; ++p) {
1695         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1696       }
1697 #endif
1698       /* B tetrahedron: {a, 1, b, e} */
1699       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
1700       orntNew[0] = ornt[0];
1701       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
1702       orntNew[1] = ornt[1];
1703       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
1704       orntNew[2] = 0;
1705       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
1706       orntNew[3] = ornt[3];
1707       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1708       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1709 #if 1
1710       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
1711       for (p = 0; p < 4; ++p) {
1712         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1713       }
1714 #endif
1715       /* C tetrahedron: {c, b, 2, f} */
1716       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
1717       orntNew[0] = ornt[0];
1718       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
1719       orntNew[1] = 0;
1720       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
1721       orntNew[2] = ornt[2];
1722       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
1723       orntNew[3] = ornt[3];
1724       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1725       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1726 #if 1
1727       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
1728       for (p = 0; p < 4; ++p) {
1729         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1730       }
1731 #endif
1732       /* D tetrahedron: {d, e, f, 3} */
1733       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
1734       orntNew[0] = 0;
1735       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
1736       orntNew[1] = ornt[1];
1737       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
1738       orntNew[2] = ornt[2];
1739       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
1740       orntNew[3] = ornt[3];
1741       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
1742       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
1743 #if 1
1744       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
1745       for (p = 0; p < 4; ++p) {
1746         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1747       }
1748 #endif
1749       /* A' tetrahedron: {d, a, c, f} */
1750       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
1751       orntNew[0] = -3;
1752       coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
1753       orntNew[1] = ornt[2] < 0 ? -(GetTetSomething_Static(ornt[2], 0)+1) : GetTetSomething_Static(ornt[2], 0);
1754       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
1755       orntNew[2] = 0;
1756       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
1757       orntNew[3] = 2;
1758       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
1759       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
1760 #if 1
1761       if ((newp+4 < cStartNew) || (newp+4 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+4, cStartNew, cEndNew);
1762       for (p = 0; p < 4; ++p) {
1763         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1764       }
1765 #endif
1766       /* B' tetrahedron: {e, b, a, f} */
1767       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
1768       orntNew[0] = -3;
1769       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
1770       orntNew[1] = 1;
1771       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
1772       orntNew[2] = 0;
1773       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + 3;
1774       orntNew[3] = ornt[3] < 0 ? -(GetTetSomething_Static(ornt[3], 0)+1) : GetTetSomething_Static(ornt[3], 0);
1775       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
1776       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
1777 #if 1
1778       if ((newp+5 < cStartNew) || (newp+5 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+5, cStartNew, cEndNew);
1779       for (p = 0; p < 4; ++p) {
1780         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1781       }
1782 #endif
1783       /* C' tetrahedron: {b, f, c, a} */
1784       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
1785       orntNew[0] = -3;
1786       coneNew[1] = fStartNew + (cone[0] - fStart)*4 + 3;
1787       orntNew[1] = ornt[0] < 0 ? -(GetTetSomething_Static(ornt[0], 2)+1) : GetTetSomething_Static(ornt[0], 2);
1788       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
1789       orntNew[2] = -3;
1790       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
1791       orntNew[3] = -2;
1792       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
1793       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
1794 #if 1
1795       if ((newp+6 < cStartNew) || (newp+6 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+6, cStartNew, cEndNew);
1796       for (p = 0; p < 4; ++p) {
1797         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1798       }
1799 #endif
1800       /* D' tetrahedron: {f, e, d, a} */
1801       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
1802       orntNew[0] = -3;
1803       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
1804       orntNew[1] = -3;
1805       coneNew[2] = fStartNew + (cone[1] - fStart)*4 + 3;
1806       orntNew[2] = ornt[1] < 0 ? -(GetTetSomething_Static(ornt[1], 0)+1) : GetTetSomething_Static(ornt[1], 0);
1807       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
1808       orntNew[3] = -3;
1809       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
1810       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
1811 #if 1
1812       if ((newp+7 < cStartNew) || (newp+7 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+7, cStartNew, cEndNew);
1813       for (p = 0; p < 4; ++p) {
1814         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1815       }
1816 #endif
1817     }
1818     /* Split faces have 3 edges and the same cells as the parent */
1819     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
1820     ierr = PetscMalloc1((2 + maxSupportSize*2), &supportRef);CHKERRQ(ierr);
1821     for (f = fStart; f < fEnd; ++f) {
1822       const PetscInt  newp = fStartNew + (f - fStart)*4;
1823       const PetscInt *cone, *ornt, *support;
1824       PetscInt        coneNew[3], orntNew[3], coneSize, supportSize, s;
1825 
1826       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1827       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
1828       /* A triangle */
1829       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
1830       orntNew[0] = ornt[0];
1831       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
1832       orntNew[1] = -2;
1833       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
1834       orntNew[2] = ornt[2];
1835       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1836       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1837 #if 1
1838       if ((newp+0 < fStartNew) || (newp+0 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+0, fStartNew, fEndNew);
1839       for (p = 0; p < 3; ++p) {
1840         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1841       }
1842 #endif
1843       /* B triangle */
1844       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
1845       orntNew[0] = ornt[0];
1846       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
1847       orntNew[1] = ornt[1];
1848       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
1849       orntNew[2] = -2;
1850       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1851       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1852 #if 1
1853       if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+1, fStartNew, fEndNew);
1854       for (p = 0; p < 3; ++p) {
1855         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1856       }
1857 #endif
1858       /* C triangle */
1859       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
1860       orntNew[0] = -2;
1861       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
1862       orntNew[1] = ornt[1];
1863       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
1864       orntNew[2] = ornt[2];
1865       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1866       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1867 #if 1
1868       if ((newp+2 < fStartNew) || (newp+2 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+2, fStartNew, fEndNew);
1869       for (p = 0; p < 3; ++p) {
1870         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1871       }
1872 #endif
1873       /* D triangle */
1874       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
1875       orntNew[0] = 0;
1876       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
1877       orntNew[1] = 0;
1878       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
1879       orntNew[2] = 0;
1880       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
1881       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
1882 #if 1
1883       if ((newp+3 < fStartNew) || (newp+3 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+3, fStartNew, fEndNew);
1884       for (p = 0; p < 3; ++p) {
1885         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1886       }
1887 #endif
1888       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1889       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1890       for (r = 0; r < 4; ++r) {
1891         for (s = 0; s < supportSize; ++s) {
1892           PetscInt subf;
1893           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1894           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1895           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1896           for (c = 0; c < coneSize; ++c) {
1897             if (cone[c] == f) break;
1898           }
1899           subf = GetTriSubfaceInverse_Static(ornt[c], r);
1900           supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
1901         }
1902         ierr = DMPlexSetSupport(rdm, newp+r, supportRef);CHKERRQ(ierr);
1903 #if 1
1904         if ((newp+r < fStartNew) || (newp+r >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+r, fStartNew, fEndNew);
1905         for (p = 0; p < supportSize; ++p) {
1906           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
1907         }
1908 #endif
1909       }
1910     }
1911     /* Interior faces have 3 edges and 2 cells */
1912     for (c = cStart; c < cEnd; ++c) {
1913       PetscInt        newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8;
1914       const PetscInt *cone, *ornt;
1915       PetscInt        coneNew[3], orntNew[3];
1916       PetscInt        supportNew[2];
1917 
1918       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1919       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1920       /* Face A: {c, a, d} */
1921       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 2);
1922       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1923       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 2);
1924       orntNew[1] = ornt[1] < 0 ? -2 : 0;
1925       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 2);
1926       orntNew[2] = ornt[2] < 0 ? -2 : 0;
1927       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1928       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1929 #if 1
1930       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1931       for (p = 0; p < 3; ++p) {
1932         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1933       }
1934 #endif
1935       supportNew[0] = (c - cStart)*8 + 0;
1936       supportNew[1] = (c - cStart)*8 + 0+4;
1937       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1938 #if 1
1939       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1940       for (p = 0; p < 2; ++p) {
1941         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1942       }
1943 #endif
1944       ++newp;
1945       /* Face B: {a, b, e} */
1946       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 0);
1947       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1948       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 0);
1949       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1950       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 1);
1951       orntNew[2] = ornt[1] < 0 ? -2 : 0;
1952       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1953       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1954 #if 1
1955       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1956       for (p = 0; p < 3; ++p) {
1957         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1958       }
1959 #endif
1960       supportNew[0] = (c - cStart)*8 + 1;
1961       supportNew[1] = (c - cStart)*8 + 1+4;
1962       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1963 #if 1
1964       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1965       for (p = 0; p < 2; ++p) {
1966         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1967       }
1968 #endif
1969       ++newp;
1970       /* Face C: {c, f, b} */
1971       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 0);
1972       orntNew[0] = ornt[2] < 0 ? -2 : 0;
1973       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 2);
1974       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1975       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 1);
1976       orntNew[2] = ornt[0] < 0 ? -2 : 0;
1977       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1978       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1979 #if 1
1980       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1981       for (p = 0; p < 3; ++p) {
1982         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1983       }
1984 #endif
1985       supportNew[0] = (c - cStart)*8 + 2;
1986       supportNew[1] = (c - cStart)*8 + 2+4;
1987       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1988 #if 1
1989       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1990       for (p = 0; p < 2; ++p) {
1991         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1992       }
1993 #endif
1994       ++newp;
1995       /* Face D: {d, e, f} */
1996       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 0);
1997       orntNew[0] = ornt[1] < 0 ? -2 : 0;
1998       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 1);
1999       orntNew[1] = ornt[3] < 0 ? -2 : 0;
2000       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 1);
2001       orntNew[2] = ornt[2] < 0 ? -2 : 0;
2002       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2003       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2004 #if 1
2005       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2006       for (p = 0; p < 3; ++p) {
2007         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2008       }
2009 #endif
2010       supportNew[0] = (c - cStart)*8 + 3;
2011       supportNew[1] = (c - cStart)*8 + 3+4;
2012       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2013 #if 1
2014       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2015       for (p = 0; p < 2; ++p) {
2016         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
2017       }
2018 #endif
2019       ++newp;
2020       /* Face E: {d, f, a} */
2021       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 1);
2022       orntNew[0] = ornt[2] < 0 ? 0 : -2;
2023       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2024       orntNew[1] = -2;
2025       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 2);
2026       orntNew[2] = ornt[1] < 0 ? -2 : 0;
2027       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2028       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2029 #if 1
2030       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2031       for (p = 0; p < 3; ++p) {
2032         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2033       }
2034 #endif
2035       supportNew[0] = (c - cStart)*8 + 0+4;
2036       supportNew[1] = (c - cStart)*8 + 3+4;
2037       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2038 #if 1
2039       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2040       for (p = 0; p < 2; ++p) {
2041         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
2042       }
2043 #endif
2044       ++newp;
2045       /* Face F: {c, a, f} */
2046       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 2);
2047       orntNew[0] = ornt[0] < 0 ? -2 : 0;
2048       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2049       orntNew[1] = 0;
2050       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 0);
2051       orntNew[2] = ornt[2] < 0 ? 0 : -2;
2052       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2053       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2054 #if 1
2055       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2056       for (p = 0; p < 3; ++p) {
2057         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2058       }
2059 #endif
2060       supportNew[0] = (c - cStart)*8 + 0+4;
2061       supportNew[1] = (c - cStart)*8 + 2+4;
2062       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2063 #if 1
2064       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2065       for (p = 0; p < 2; ++p) {
2066         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
2067       }
2068 #endif
2069       ++newp;
2070       /* Face G: {e, a, f} */
2071       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 1);
2072       orntNew[0] = ornt[1] < 0 ? -2 : 0;
2073       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2074       orntNew[1] = 0;
2075       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 1);
2076       orntNew[2] = ornt[3] < 0 ? 0 : -2;
2077       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2078       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2079 #if 1
2080       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2081       for (p = 0; p < 3; ++p) {
2082         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2083       }
2084 #endif
2085       supportNew[0] = (c - cStart)*8 + 1+4;
2086       supportNew[1] = (c - cStart)*8 + 3+4;
2087       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2088 #if 1
2089       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2090       for (p = 0; p < 2; ++p) {
2091         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
2092       }
2093 #endif
2094       ++newp;
2095       /* Face H: {a, b, f} */
2096       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 0);
2097       orntNew[0] = ornt[0] < 0 ? -2 : 0;
2098       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 2);
2099       orntNew[1] = ornt[3] < 0 ? 0 : -2;
2100       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2101       orntNew[2] = -2;
2102       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2103       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2104 #if 1
2105       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2106       for (p = 0; p < 3; ++p) {
2107         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2108       }
2109 #endif
2110       supportNew[0] = (c - cStart)*8 + 1+4;
2111       supportNew[1] = (c - cStart)*8 + 2+4;
2112       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2113 #if 1
2114       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2115       for (p = 0; p < 2; ++p) {
2116         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
2117       }
2118 #endif
2119       ++newp;
2120     }
2121     /* Split Edges have 2 vertices and the same faces as the parent */
2122     for (e = eStart; e < eEnd; ++e) {
2123       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
2124 
2125       for (r = 0; r < 2; ++r) {
2126         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
2127         const PetscInt *cone, *ornt, *support;
2128         PetscInt        coneNew[2], coneSize, c, supportSize, s;
2129 
2130         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
2131         coneNew[0]       = vStartNew + (cone[0] - vStart);
2132         coneNew[1]       = vStartNew + (cone[1] - vStart);
2133         coneNew[(r+1)%2] = newv;
2134         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2135 #if 1
2136         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2137         for (p = 0; p < 2; ++p) {
2138           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2139         }
2140 #endif
2141         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
2142         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
2143         for (s = 0; s < supportSize; ++s) {
2144           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2145           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2146           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
2147           for (c = 0; c < coneSize; ++c) {
2148             if (cone[c] == e) break;
2149           }
2150           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
2151         }
2152         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2153 #if 1
2154         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2155         for (p = 0; p < supportSize; ++p) {
2156           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
2157         }
2158 #endif
2159       }
2160     }
2161     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
2162     for (f = fStart; f < fEnd; ++f) {
2163       const PetscInt *cone, *ornt, *support;
2164       PetscInt        coneSize, supportSize, s;
2165 
2166       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
2167       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2168       for (r = 0; r < 3; ++r) {
2169         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
2170         PetscInt        coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
2171         PetscInt        fint[24] = { 1,  7, -1, -1,  0,  5,
2172                                     -1, -1,  1,  6,  0,  4,
2173                                      2,  5,  3,  4, -1, -1,
2174                                     -1, -1,  3,  6,  2,  7};
2175 
2176         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
2177         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
2178         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
2179         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2180 #if 1
2181         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2182         for (p = 0; p < 2; ++p) {
2183           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2184         }
2185 #endif
2186         supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
2187         supportRef[1] = fStartNew + (f - fStart)*4 + 3;
2188         for (s = 0; s < supportSize; ++s) {
2189           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2190           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2191           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
2192           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
2193           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
2194           er = GetTetSomethingInverse_Static(ornt[c], r);
2195           if (er == eint[c]) {
2196             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
2197           } else {
2198             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
2199             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
2200           }
2201         }
2202         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2203 #if 1
2204         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2205         for (p = 0; p < intFaces; ++p) {
2206           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
2207         }
2208 #endif
2209       }
2210     }
2211     /* Interior edges have 2 vertices and 4 faces */
2212     for (c = cStart; c < cEnd; ++c) {
2213       const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2214       const PetscInt *cone, *ornt, *fcone;
2215       PetscInt        coneNew[2], supportNew[4], find;
2216 
2217       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2218       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2219       ierr = DMPlexGetCone(dm, cone[0], &fcone);CHKERRQ(ierr);
2220       find = GetTriEdge_Static(ornt[0], 0);
2221       coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
2222       ierr = DMPlexGetCone(dm, cone[2], &fcone);CHKERRQ(ierr);
2223       find = GetTriEdge_Static(ornt[2], 1);
2224       coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
2225       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2226 #if 1
2227       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2228       for (p = 0; p < 2; ++p) {
2229         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2230       }
2231 #endif
2232       supportNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
2233       supportNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
2234       supportNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
2235       supportNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
2236       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2237 #if 1
2238       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2239       for (p = 0; p < 4; ++p) {
2240         if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportNew[p], fStartNew, fEndNew);
2241       }
2242 #endif
2243     }
2244     /* Old vertices have identical supports */
2245     for (v = vStart; v < vEnd; ++v) {
2246       const PetscInt  newp = vStartNew + (v - vStart);
2247       const PetscInt *support, *cone;
2248       PetscInt        size, s;
2249 
2250       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
2251       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
2252       for (s = 0; s < size; ++s) {
2253         PetscInt r = 0;
2254 
2255         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2256         if (cone[1] == v) r = 1;
2257         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
2258       }
2259       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2260 #if 1
2261       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2262       for (p = 0; p < size; ++p) {
2263         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
2264       }
2265 #endif
2266     }
2267     /* Edge vertices have 2 + face*2 + 0/1 supports */
2268     for (e = eStart; e < eEnd; ++e) {
2269       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
2270       const PetscInt *cone, *support;
2271       PetscInt       *star = NULL, starSize, cellSize = 0, coneSize, size, s;
2272 
2273       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
2274       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
2275       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
2276       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
2277       for (s = 0; s < size; ++s) {
2278         PetscInt r = 0;
2279 
2280         ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2281         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2282         for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
2283         supportRef[2+s*2+0] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
2284         supportRef[2+s*2+1] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
2285       }
2286       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
2287       for (s = 0; s < starSize*2; s += 2) {
2288         const PetscInt *cone, *ornt;
2289         PetscInt        e01, e23;
2290 
2291         if ((star[s] >= cStart) && (star[s] < cEnd)) {
2292           /* Check edge 0-1 */
2293           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
2294           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
2295           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
2296           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
2297           /* Check edge 2-3 */
2298           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
2299           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
2300           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
2301           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
2302           if ((e01 == e) || (e23 == e)) {supportRef[2+size*2+cellSize++] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (star[s] - cStart);}
2303         }
2304       }
2305       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
2306       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2307 #if 1
2308       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2309       for (p = 0; p < 2+size*2+cellSize; ++p) {
2310         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
2311       }
2312 #endif
2313     }
2314     ierr = PetscFree(supportRef);CHKERRQ(ierr);
2315     ierr = DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);CHKERRQ(ierr);
2316     break;
2317   case 7:
2318     /* Hybrid Simplicial 3D */
2319     ierr = DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);CHKERRQ(ierr);
2320     /* Interior cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
2321     ierr = DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);CHKERRQ(ierr);
2322     for (c = cStart; c < cMax; ++c) {
2323       const PetscInt  newp = cStartNew + (c - cStart)*8;
2324       const PetscInt *cone, *ornt;
2325       PetscInt        coneNew[4], orntNew[4];
2326 
2327       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2328       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2329       /* A tetrahedron: {0, a, c, d} */
2330       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
2331       orntNew[0] = ornt[0];
2332       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
2333       orntNew[1] = ornt[1];
2334       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
2335       orntNew[2] = ornt[2];
2336       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 0;
2337       orntNew[3] = 0;
2338       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
2339       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
2340 #if 1
2341       if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cMaxNew);
2342       for (p = 0; p < 4; ++p) {
2343         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2344       }
2345 #endif
2346       /* B tetrahedron: {a, 1, b, e} */
2347       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
2348       orntNew[0] = ornt[0];
2349       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
2350       orntNew[1] = ornt[1];
2351       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 1;
2352       orntNew[2] = 0;
2353       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
2354       orntNew[3] = ornt[3];
2355       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
2356       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
2357 #if 1
2358       if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cMaxNew);
2359       for (p = 0; p < 4; ++p) {
2360         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2361       }
2362 #endif
2363       /* C tetrahedron: {c, b, 2, f} */
2364       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
2365       orntNew[0] = ornt[0];
2366       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 2;
2367       orntNew[1] = 0;
2368       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
2369       orntNew[2] = ornt[2];
2370       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
2371       orntNew[3] = ornt[3];
2372       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
2373       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
2374 #if 1
2375       if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cMaxNew);
2376       for (p = 0; p < 4; ++p) {
2377         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2378       }
2379 #endif
2380       /* D tetrahedron: {d, e, f, 3} */
2381       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 3;
2382       orntNew[0] = 0;
2383       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
2384       orntNew[1] = ornt[1];
2385       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
2386       orntNew[2] = ornt[2];
2387       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
2388       orntNew[3] = ornt[3];
2389       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
2390       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
2391 #if 1
2392       if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cMaxNew);
2393       for (p = 0; p < 4; ++p) {
2394         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2395       }
2396 #endif
2397       /* A' tetrahedron: {d, a, c, f} */
2398       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 0;
2399       orntNew[0] = -3;
2400       coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
2401       orntNew[1] = ornt[2] < 0 ? -(GetTetSomething_Static(ornt[2], 0)+1) : GetTetSomething_Static(ornt[2], 0);
2402       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 5;
2403       orntNew[2] = 0;
2404       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 4;
2405       orntNew[3] = 2;
2406       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
2407       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
2408 #if 1
2409       if ((newp+4 < cStartNew) || (newp+4 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+4, cStartNew, cMaxNew);
2410       for (p = 0; p < 4; ++p) {
2411         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2412       }
2413 #endif
2414       /* B' tetrahedron: {e, b, a, f} */
2415       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 1;
2416       orntNew[0] = -3;
2417       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 6;
2418       orntNew[1] = 1;
2419       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 7;
2420       orntNew[2] = 0;
2421       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + 3;
2422       orntNew[3] = ornt[3] < 0 ? -(GetTetSomething_Static(ornt[3], 0)+1) : GetTetSomething_Static(ornt[3], 0);
2423       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
2424       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
2425 #if 1
2426       if ((newp+5 < cStartNew) || (newp+5 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+5, cStartNew, cMaxNew);
2427       for (p = 0; p < 4; ++p) {
2428         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2429       }
2430 #endif
2431       /* C' tetrahedron: {b, f, c, a} */
2432       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 2;
2433       orntNew[0] = -3;
2434       coneNew[1] = fStartNew + (cone[0] - fStart)*4 + 3;
2435       orntNew[1] = ornt[0] < 0 ? -(GetTetSomething_Static(ornt[0], 2)+1) : GetTetSomething_Static(ornt[0], 2);
2436       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 5;
2437       orntNew[2] = -3;
2438       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 7;
2439       orntNew[3] = -2;
2440       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
2441       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
2442 #if 1
2443       if ((newp+6 < cStartNew) || (newp+6 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+6, cStartNew, cMaxNew);
2444       for (p = 0; p < 4; ++p) {
2445         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2446       }
2447 #endif
2448       /* D' tetrahedron: {f, e, d, a} */
2449       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 3;
2450       orntNew[0] = -3;
2451       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 4;
2452       orntNew[1] = -3;
2453       coneNew[2] = fStartNew + (cone[1] - fStart)*4 + 3;
2454       orntNew[2] = ornt[1] < 0 ? -(GetTetSomething_Static(ornt[1], 0)+1) : GetTetSomething_Static(ornt[1], 0);
2455       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 6;
2456       orntNew[3] = -3;
2457       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
2458       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
2459 #if 1
2460       if ((newp+7 < cStartNew) || (newp+7 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+7, cStartNew, cMaxNew);
2461       for (p = 0; p < 4; ++p) {
2462         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2463       }
2464 #endif
2465     }
2466     /* Hybrid cells have 5 faces */
2467     for (c = cMax; c < cEnd; ++c) {
2468       const PetscInt  newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4;
2469       const PetscInt *cone, *ornt, *fornt;
2470       PetscInt        coneNew[5], orntNew[5], o, of;
2471 
2472       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2473       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2474       ierr = DMPlexGetConeOrientation(dm, cone[0], &fornt);CHKERRQ(ierr);
2475       o = ornt[0] < 0 ? -1 : 1;
2476       for (r = 0; r < 3; ++r) {
2477         coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], r);
2478         orntNew[0] = ornt[0];
2479         coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], r);
2480         orntNew[1] = ornt[1];
2481         of = fornt[GetTriEdge_Static(ornt[0], (r+2)%3)] < 0 ? -1 : 1;
2482         coneNew[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], (r+2)%3)] - fMax)*2 + (o*of < 0 ? 0 : 1);
2483         orntNew[2] = 0;
2484         of = fornt[GetTriEdge_Static(ornt[0], r)]       < 0 ? -1 : 1;
2485         coneNew[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], r)]       - fMax)*2 + (o*of < 0 ? 1 : 0);
2486         orntNew[3] = 0;
2487         coneNew[4] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + GetTriSubface_Static(ornt[0], r);
2488         orntNew[4] = 0;
2489         ierr = DMPlexSetCone(rdm, newp+r, coneNew);CHKERRQ(ierr);
2490         ierr = DMPlexSetConeOrientation(rdm, newp+r, orntNew);CHKERRQ(ierr);
2491 #if 1
2492         if ((newp+r < cMaxNew) || (newp+r >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", newp+r, cMaxNew, cEndNew);
2493         for (p = 0; p < 2; ++p) {
2494           if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2495         }
2496         for (p = 2; p < 5; ++p) {
2497           if ((coneNew[p] < fMaxNew)   || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", coneNew[p], fMaxNew, fEndNew);
2498         }
2499 #endif
2500       }
2501       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + 3;
2502       orntNew[0] = 0;
2503       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + 3;
2504       orntNew[1] = 0;
2505       coneNew[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;
2506       orntNew[2] = 0;
2507       coneNew[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;
2508       orntNew[3] = 0;
2509       coneNew[4] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;
2510       orntNew[4] = 0;
2511       ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
2512       ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
2513 #if 1
2514       if ((newp+3 < cMaxNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", newp+3, cMaxNew, cEndNew);
2515       for (p = 0; p < 2; ++p) {
2516         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2517       }
2518       for (p = 2; p < 5; ++p) {
2519         if ((coneNew[p] < fMaxNew)   || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", coneNew[p], fMaxNew, fEndNew);
2520       }
2521 #endif
2522     }
2523     /* Split faces have 3 edges and the same cells as the parent */
2524     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
2525     ierr = PetscMalloc1((2 + maxSupportSize*2), &supportRef);CHKERRQ(ierr);
2526     for (f = fStart; f < fMax; ++f) {
2527       const PetscInt  newp = fStartNew + (f - fStart)*4;
2528       const PetscInt *cone, *ornt, *support;
2529       PetscInt        coneNew[3], orntNew[3], coneSize, supportSize, s;
2530 
2531       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
2532       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
2533       /* A triangle */
2534       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
2535       orntNew[0] = ornt[0];
2536       coneNew[1] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
2537       orntNew[1] = -2;
2538       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
2539       orntNew[2] = ornt[2];
2540       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
2541       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
2542 #if 1
2543       if ((newp+0 < fStartNew) || (newp+0 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+0, fStartNew, fMaxNew);
2544       for (p = 0; p < 3; ++p) {
2545         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2546       }
2547 #endif
2548       /* B triangle */
2549       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
2550       orntNew[0] = ornt[0];
2551       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
2552       orntNew[1] = ornt[1];
2553       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
2554       orntNew[2] = -2;
2555       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
2556       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
2557 #if 1
2558       if ((newp+1 < fStartNew) || (newp+1 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+1, fStartNew, fMaxNew);
2559       for (p = 0; p < 3; ++p) {
2560         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2561       }
2562 #endif
2563       /* C triangle */
2564       coneNew[0] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
2565       orntNew[0] = -2;
2566       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
2567       orntNew[1] = ornt[1];
2568       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
2569       orntNew[2] = ornt[2];
2570       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
2571       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
2572 #if 1
2573       if ((newp+2 < fStartNew) || (newp+2 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+2, fStartNew, fMaxNew);
2574       for (p = 0; p < 3; ++p) {
2575         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2576       }
2577 #endif
2578       /* D triangle */
2579       coneNew[0] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
2580       orntNew[0] = 0;
2581       coneNew[1] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
2582       orntNew[1] = 0;
2583       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
2584       orntNew[2] = 0;
2585       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
2586       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
2587 #if 1
2588       if ((newp+3 < fStartNew) || (newp+3 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+3, fStartNew, fMaxNew);
2589       for (p = 0; p < 3; ++p) {
2590         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2591       }
2592 #endif
2593       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
2594       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2595       for (r = 0; r < 4; ++r) {
2596         for (s = 0; s < supportSize; ++s) {
2597           PetscInt subf;
2598           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2599           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2600           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
2601           for (c = 0; c < coneSize; ++c) {
2602             if (cone[c] == f) break;
2603           }
2604           subf = GetTriSubfaceInverse_Static(ornt[c], r);
2605           if (support[s] < cMax) {
2606             supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
2607           } else {
2608             supportRef[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (r==3 ? r : subf);
2609           }
2610         }
2611         ierr = DMPlexSetSupport(rdm, newp+r, supportRef);CHKERRQ(ierr);
2612 #if 1
2613         if ((newp+r < fStartNew) || (newp+r >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+r, fStartNew, fMaxNew);
2614         for (p = 0; p < supportSize; ++p) {
2615           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
2616         }
2617 #endif
2618       }
2619     }
2620     /* Interior cell faces have 3 edges and 2 cells */
2621     for (c = cStart; c < cMax; ++c) {
2622       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8;
2623       const PetscInt *cone, *ornt;
2624       PetscInt        coneNew[3], orntNew[3];
2625       PetscInt        supportNew[2];
2626 
2627       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2628       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2629       /* Face A: {c, a, d} */
2630       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 2);
2631       orntNew[0] = ornt[0] < 0 ? -2 : 0;
2632       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 2);
2633       orntNew[1] = ornt[1] < 0 ? -2 : 0;
2634       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 2);
2635       orntNew[2] = ornt[2] < 0 ? -2 : 0;
2636       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2637       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2638 #if 1
2639       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2640       for (p = 0; p < 3; ++p) {
2641         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2642       }
2643 #endif
2644       supportNew[0] = (c - cStart)*8 + 0;
2645       supportNew[1] = (c - cStart)*8 + 0+4;
2646       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2647 #if 1
2648       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2649       for (p = 0; p < 2; ++p) {
2650         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
2651       }
2652 #endif
2653       ++newp;
2654       /* Face B: {a, b, e} */
2655       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 0);
2656       orntNew[0] = ornt[0] < 0 ? -2 : 0;
2657       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 0);
2658       orntNew[1] = ornt[3] < 0 ? -2 : 0;
2659       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 1);
2660       orntNew[2] = ornt[1] < 0 ? -2 : 0;
2661       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2662       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2663 #if 1
2664       if ((newp+1 < fStartNew) || (newp+1 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+1, fStartNew, fMaxNew);
2665       for (p = 0; p < 3; ++p) {
2666         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2667       }
2668 #endif
2669       supportNew[0] = (c - cStart)*8 + 1;
2670       supportNew[1] = (c - cStart)*8 + 1+4;
2671       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2672 #if 1
2673       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2674       for (p = 0; p < 2; ++p) {
2675         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
2676       }
2677 #endif
2678       ++newp;
2679       /* Face C: {c, f, b} */
2680       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 0);
2681       orntNew[0] = ornt[2] < 0 ? -2 : 0;
2682       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 2);
2683       orntNew[1] = ornt[3] < 0 ? -2 : 0;
2684       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 1);
2685       orntNew[2] = ornt[0] < 0 ? -2 : 0;
2686       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2687       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2688 #if 1
2689       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2690       for (p = 0; p < 3; ++p) {
2691         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2692       }
2693 #endif
2694       supportNew[0] = (c - cStart)*8 + 2;
2695       supportNew[1] = (c - cStart)*8 + 2+4;
2696       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2697 #if 1
2698       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2699       for (p = 0; p < 2; ++p) {
2700         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
2701       }
2702 #endif
2703       ++newp;
2704       /* Face D: {d, e, f} */
2705       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 0);
2706       orntNew[0] = ornt[1] < 0 ? -2 : 0;
2707       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 1);
2708       orntNew[1] = ornt[3] < 0 ? -2 : 0;
2709       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 1);
2710       orntNew[2] = ornt[2] < 0 ? -2 : 0;
2711       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2712       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2713 #if 1
2714       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2715       for (p = 0; p < 3; ++p) {
2716         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2717       }
2718 #endif
2719       supportNew[0] = (c - cStart)*8 + 3;
2720       supportNew[1] = (c - cStart)*8 + 3+4;
2721       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2722 #if 1
2723       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2724       for (p = 0; p < 2; ++p) {
2725         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
2726       }
2727 #endif
2728       ++newp;
2729       /* Face E: {d, f, a} */
2730       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 1);
2731       orntNew[0] = ornt[2] < 0 ? 0 : -2;
2732       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
2733       orntNew[1] = -2;
2734       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 2);
2735       orntNew[2] = ornt[1] < 0 ? -2 : 0;
2736       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2737       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2738 #if 1
2739       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2740       for (p = 0; p < 3; ++p) {
2741         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2742       }
2743 #endif
2744       supportNew[0] = (c - cStart)*8 + 0+4;
2745       supportNew[1] = (c - cStart)*8 + 3+4;
2746       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2747 #if 1
2748       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2749       for (p = 0; p < 2; ++p) {
2750         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
2751       }
2752 #endif
2753       ++newp;
2754       /* Face F: {c, a, f} */
2755       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 2);
2756       orntNew[0] = ornt[0] < 0 ? -2 : 0;
2757       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
2758       orntNew[1] = 0;
2759       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 0);
2760       orntNew[2] = ornt[2] < 0 ? 0 : -2;
2761       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2762       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2763 #if 1
2764       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2765       for (p = 0; p < 3; ++p) {
2766         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2767       }
2768 #endif
2769       supportNew[0] = (c - cStart)*8 + 0+4;
2770       supportNew[1] = (c - cStart)*8 + 2+4;
2771       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2772 #if 1
2773       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2774       for (p = 0; p < 2; ++p) {
2775         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
2776       }
2777 #endif
2778       ++newp;
2779       /* Face G: {e, a, f} */
2780       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 1);
2781       orntNew[0] = ornt[1] < 0 ? -2 : 0;
2782       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
2783       orntNew[1] = 0;
2784       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 1);
2785       orntNew[2] = ornt[3] < 0 ? 0 : -2;
2786       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2787       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2788 #if 1
2789       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2790       for (p = 0; p < 3; ++p) {
2791         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2792       }
2793 #endif
2794       supportNew[0] = (c - cStart)*8 + 1+4;
2795       supportNew[1] = (c - cStart)*8 + 3+4;
2796       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2797 #if 1
2798       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2799       for (p = 0; p < 2; ++p) {
2800         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
2801       }
2802 #endif
2803       ++newp;
2804       /* Face H: {a, b, f} */
2805       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 0);
2806       orntNew[0] = ornt[0] < 0 ? -2 : 0;
2807       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 2);
2808       orntNew[1] = ornt[3] < 0 ? 0 : -2;
2809       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
2810       orntNew[2] = -2;
2811       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2812       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2813 #if 1
2814       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2815       for (p = 0; p < 3; ++p) {
2816         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2817       }
2818 #endif
2819       supportNew[0] = (c - cStart)*8 + 1+4;
2820       supportNew[1] = (c - cStart)*8 + 2+4;
2821       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2822 #if 1
2823       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2824       for (p = 0; p < 2; ++p) {
2825         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
2826       }
2827 #endif
2828       ++newp;
2829     }
2830     /* Hybrid split faces have 4 edges and same cells */
2831     for (f = fMax; f < fEnd; ++f) {
2832       const PetscInt *cone, *ornt, *support;
2833       PetscInt        coneNew[4], orntNew[4];
2834       PetscInt        supportNew[2], size, s, c;
2835 
2836       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
2837       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
2838       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
2839       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2840       for (r = 0; r < 2; ++r) {
2841         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;
2842 
2843         coneNew[0]   = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
2844         orntNew[0]   = ornt[0];
2845         coneNew[1]   = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
2846         orntNew[1]   = ornt[1];
2847         coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (cone[2+r] - eMax);
2848         orntNew[2+r] = 0;
2849         coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd      - eMax) + (f - fMax);
2850         orntNew[3-r] = 0;
2851         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2852         ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
2853 #if 1
2854         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
2855         for (p = 0; p < 2; ++p) {
2856           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2857         }
2858         for (p = 2; p < 4; ++p) {
2859           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", coneNew[p], eMaxNew, eEndNew);
2860         }
2861 #endif
2862         for (s = 0; s < size; ++s) {
2863           const PetscInt *coneCell, *orntCell, *fornt;
2864           PetscInt        o, of;
2865 
2866           ierr = DMPlexGetCone(dm, support[s], &coneCell);CHKERRQ(ierr);
2867           ierr = DMPlexGetConeOrientation(dm, support[s], &orntCell);CHKERRQ(ierr);
2868           o = orntCell[0] < 0 ? -1 : 1;
2869           for (c = 2; c < 5; ++c) if (coneCell[c] == f) break;
2870           if (c >= 5) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of cell %d", f, support[s]);
2871           ierr = DMPlexGetConeOrientation(dm, coneCell[0], &fornt);CHKERRQ(ierr);
2872           of = fornt[c-2] < 0 ? -1 : 1;
2873           supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetTriEdgeInverse_Static(orntCell[0], c-2) + (o*of < 0 ? 1-r : r))%3;
2874         }
2875         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
2876 #if 1
2877         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
2878         for (p = 0; p < size; ++p) {
2879           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", supportNew[p], cMaxNew, cEndNew);
2880         }
2881 #endif
2882       }
2883     }
2884     /* Hybrid cell faces have 4 edges and 2 cells */
2885     for (c = cMax; c < cEnd; ++c) {
2886       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3;
2887       const PetscInt *cone, *ornt;
2888       PetscInt        coneNew[4], orntNew[4];
2889       PetscInt        supportNew[2];
2890 
2891       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2892       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
2893       for (r = 0; r < 3; ++r) {
2894         coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + (r+2)%3;
2895         orntNew[0] = 0;
2896         coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + (r+2)%3;
2897         orntNew[1] = 0;
2898         coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+(r+2)%3] - fMax);
2899         orntNew[2] = 0;
2900         coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+r]       - fMax);
2901         orntNew[3] = 0;
2902         ierr = DMPlexSetCone(rdm, newp+r, coneNew);CHKERRQ(ierr);
2903         ierr = DMPlexSetConeOrientation(rdm, newp+r, orntNew);CHKERRQ(ierr);
2904 #if 1
2905         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp+r, fMaxNew, fEndNew);
2906         for (p = 0; p < 2; ++p) {
2907           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
2908         }
2909         for (p = 2; p < 4; ++p) {
2910           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", coneNew[p], eMaxNew, eEndNew);
2911         }
2912 #endif
2913         supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetTriSubface_Static(ornt[0], r);
2914         supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + 3;
2915         ierr          = DMPlexSetSupport(rdm, newp+r, supportNew);CHKERRQ(ierr);
2916 #if 1
2917         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp+r, fMaxNew, fEndNew);
2918         for (p = 0; p < 2; ++p) {
2919           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", supportNew[p], cMaxNew, cEndNew);
2920         }
2921 #endif
2922       }
2923     }
2924     /* Interior split edges have 2 vertices and the same faces as the parent */
2925     for (e = eStart; e < eMax; ++e) {
2926       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
2927 
2928       for (r = 0; r < 2; ++r) {
2929         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
2930         const PetscInt *cone, *ornt, *support;
2931         PetscInt        coneNew[2], coneSize, c, supportSize, s;
2932 
2933         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
2934         coneNew[0]       = vStartNew + (cone[0] - vStart);
2935         coneNew[1]       = vStartNew + (cone[1] - vStart);
2936         coneNew[(r+1)%2] = newv;
2937         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2938 #if 1
2939         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
2940         for (p = 0; p < 2; ++p) {
2941           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2942         }
2943 #endif
2944         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
2945         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
2946         for (s = 0; s < supportSize; ++s) {
2947           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2948           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2949           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
2950           for (c = 0; c < coneSize; ++c) if (cone[c] == e) break;
2951           if (support[s] < fMax) {
2952             supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
2953           } else {
2954             supportRef[s] = fStartNew + (fMax       - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
2955           }
2956         }
2957         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
2958 #if 1
2959         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
2960         for (p = 0; p < supportSize; ++p) {
2961           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid face [%d, %d)", supportRef[p], fStartNew, fEndNew);
2962         }
2963 #endif
2964       }
2965     }
2966     /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
2967     for (f = fStart; f < fMax; ++f) {
2968       const PetscInt *cone, *ornt, *support;
2969       PetscInt        coneSize, supportSize, s;
2970 
2971       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
2972       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2973       for (r = 0; r < 3; ++r) {
2974         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
2975         PetscInt        coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
2976         PetscInt        fint[24] = { 1,  7, -1, -1,  0,  5,
2977                                     -1, -1,  1,  6,  0,  4,
2978                                      2,  5,  3,  4, -1, -1,
2979                                     -1, -1,  3,  6,  2,  7};
2980 
2981         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
2982         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
2983         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
2984         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
2985 #if 1
2986         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
2987         for (p = 0; p < 2; ++p) {
2988           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2989         }
2990 #endif
2991         supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
2992         supportRef[1] = fStartNew + (f - fStart)*4 + 3;
2993         for (s = 0; s < supportSize; ++s) {
2994           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2995           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2996           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
2997           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
2998           if (support[s] < cMax) {
2999             /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
3000             er = GetTetSomethingInverse_Static(ornt[c], r);
3001             if (er == eint[c]) {
3002               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
3003             } else {
3004               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
3005               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
3006             }
3007           } else {
3008             supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (r + 1)%3;
3009           }
3010         }
3011         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3012 #if 1
3013         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3014         for (p = 0; p < intFaces; ++p) {
3015           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid face [%d, %d)", supportRef[p], fStartNew, fEndNew);
3016         }
3017 #endif
3018       }
3019     }
3020     /* Interior cell edges have 2 vertices and 4 faces */
3021     for (c = cStart; c < cMax; ++c) {
3022       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3023       const PetscInt *cone, *ornt, *fcone;
3024       PetscInt        coneNew[2], supportNew[4], find;
3025 
3026       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
3027       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
3028       ierr = DMPlexGetCone(dm, cone[0], &fcone);CHKERRQ(ierr);
3029       find = GetTriEdge_Static(ornt[0], 0);
3030       coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
3031       ierr = DMPlexGetCone(dm, cone[2], &fcone);CHKERRQ(ierr);
3032       find = GetTriEdge_Static(ornt[2], 1);
3033       coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
3034       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3035 #if 1
3036       if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3037       for (p = 0; p < 2; ++p) {
3038         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
3039       }
3040 #endif
3041       supportNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
3042       supportNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
3043       supportNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
3044       supportNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
3045       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3046 #if 1
3047       if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3048       for (p = 0; p < 4; ++p) {
3049         if ((supportNew[p] < fStartNew) || (supportNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportNew[p], fStartNew, fMaxNew);
3050       }
3051 #endif
3052     }
3053     /* Hybrid edges have two vertices and the same faces */
3054     for (e = eMax; e < eEnd; ++e) {
3055       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
3056       const PetscInt *cone, *support, *fcone;
3057       PetscInt        coneNew[2], size, fsize, s;
3058 
3059       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
3060       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
3061       ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
3062       coneNew[0] = vStartNew + (cone[0] - vStart);
3063       coneNew[1] = vStartNew + (cone[1] - vStart);
3064       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3065 #if 1
3066       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
3067       for (p = 0; p < 2; ++p) {
3068         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
3069       }
3070 #endif
3071       for (s = 0; s < size; ++s) {
3072         ierr = DMPlexGetConeSize(dm, support[s], &fsize);CHKERRQ(ierr);
3073         ierr = DMPlexGetCone(dm, support[s], &fcone);CHKERRQ(ierr);
3074         for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
3075         if ((c < 2) || (c > 3)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge %d not found in cone of face %d", e, support[s]);
3076         supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + c-2;
3077       }
3078       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3079 #if 1
3080       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
3081       for (p = 0; p < size; ++p) {
3082         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", supportRef[p], fMaxNew, fEndNew);
3083       }
3084 #endif
3085     }
3086     /* Hybrid face edges have 2 vertices and 2+2*cells faces */
3087     for (f = fMax; f < fEnd; ++f) {
3088       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
3089       const PetscInt *cone, *support, *ccone, *cornt;
3090       PetscInt        coneNew[2], size, csize, s;
3091 
3092       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
3093       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
3094       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
3095       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
3096       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
3097       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3098 #if 1
3099       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
3100       for (p = 0; p < 2; ++p) {
3101         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
3102       }
3103 #endif
3104       supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 0;
3105       supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 1;
3106       for (s = 0; s < size; ++s) {
3107         ierr = DMPlexGetConeSize(dm, support[s], &csize);CHKERRQ(ierr);
3108         ierr = DMPlexGetCone(dm, support[s], &ccone);CHKERRQ(ierr);
3109         ierr = DMPlexGetConeOrientation(dm, support[s], &cornt);CHKERRQ(ierr);
3110         for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
3111         if ((c < 2) || (c >= csize)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Hybrid face %d is not in cone of hybrid cell %d", f, support[s]);
3112         supportRef[2+s*2+0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + c-2;
3113         supportRef[2+s*2+1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (c-1)%3;
3114       }
3115       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3116 #if 1
3117       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
3118       for (p = 0; p < 2+size*2; ++p) {
3119         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", supportRef[p], fMaxNew, fEndNew);
3120       }
3121 #endif
3122     }
3123     /* Interior vertices have identical supports */
3124     for (v = vStart; v < vEnd; ++v) {
3125       const PetscInt  newp = vStartNew + (v - vStart);
3126       const PetscInt *support, *cone;
3127       PetscInt        size, s;
3128 
3129       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
3130       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
3131       for (s = 0; s < size; ++s) {
3132         PetscInt r = 0;
3133 
3134         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3135         if (cone[1] == v) r = 1;
3136         if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
3137         else                   supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (support[s] - eMax);
3138       }
3139       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3140 #if 1
3141       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3142       for (p = 0; p < size; ++p) {
3143         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
3144       }
3145 #endif
3146     }
3147     /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
3148     for (e = eStart; e < eMax; ++e) {
3149       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
3150       const PetscInt *cone, *support;
3151       PetscInt       *star = NULL, starSize, faceSize = 0, cellSize = 0, coneSize, size, s;
3152 
3153       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
3154       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
3155       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
3156       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
3157       for (s = 0; s < size; ++s) {
3158         PetscInt r = 0;
3159 
3160         if (support[s] < fMax) {
3161           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
3162           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3163           for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
3164           supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
3165           supportRef[2+faceSize+1] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
3166           faceSize += 2;
3167         } else {
3168           supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (fMax       - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (support[s] - fMax);
3169           ++faceSize;
3170         }
3171       }
3172       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
3173       for (s = 0; s < starSize*2; s += 2) {
3174         const PetscInt *cone, *ornt;
3175         PetscInt        e01, e23;
3176 
3177         if ((star[s] >= cStart) && (star[s] < cMax)) {
3178           /* Check edge 0-1 */
3179           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
3180           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
3181           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
3182           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
3183           /* Check edge 2-3 */
3184           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
3185           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
3186           ierr = DMPlexGetCone(dm, cone[2], &cone);CHKERRQ(ierr);
3187           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
3188           if ((e01 == e) || (e23 == e)) {supportRef[2+faceSize+cellSize++] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (star[s] - cStart);}
3189         }
3190       }
3191       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
3192       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3193 #if 1
3194       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3195       for (p = 0; p < 2+faceSize+cellSize; ++p) {
3196         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
3197       }
3198 #endif
3199     }
3200     ierr = PetscFree(supportRef);CHKERRQ(ierr);
3201     ierr = DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);CHKERRQ(ierr);
3202     break;
3203   case 6:
3204     /* Hex 3D */
3205     /*
3206      Bottom (viewed from top)    Top
3207      1---------2---------2       7---------2---------6
3208      |         |         |       |         |         |
3209      |    B    2    C    |       |    H    2    G    |
3210      |         |         |       |         |         |
3211      3----3----0----1----1       3----3----0----1----1
3212      |         |         |       |         |         |
3213      |    A    0    D    |       |    E    0    F    |
3214      |         |         |       |         |         |
3215      0---------0---------3       4---------0---------5
3216      */
3217     /* All cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
3218     for (c = cStart; c < cEnd; ++c) {
3219       const PetscInt  newp = (c - cStart)*8;
3220       const PetscInt *cone, *ornt;
3221       PetscInt        coneNew[6], orntNew[6];
3222 
3223       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
3224       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
3225       /* A hex */
3226       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
3227       orntNew[0] = ornt[0];
3228       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
3229       orntNew[1] = 0;
3230       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
3231       orntNew[2] = ornt[2];
3232       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
3233       orntNew[3] = 0;
3234       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
3235       orntNew[4] = 0;
3236       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
3237       orntNew[5] = ornt[5];
3238       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
3239       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
3240 #if 1
3241       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
3242       for (p = 0; p < 6; ++p) {
3243         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
3244       }
3245 #endif
3246       /* B hex */
3247       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
3248       orntNew[0] = ornt[0];
3249       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
3250       orntNew[1] = 0;
3251       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
3252       orntNew[2] = -1;
3253       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
3254       orntNew[3] = ornt[3];
3255       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
3256       orntNew[4] = 0;
3257       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
3258       orntNew[5] = ornt[5];
3259       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
3260       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
3261 #if 1
3262       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
3263       for (p = 0; p < 6; ++p) {
3264         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
3265       }
3266 #endif
3267       /* C hex */
3268       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
3269       orntNew[0] = ornt[0];
3270       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
3271       orntNew[1] = 0;
3272       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
3273       orntNew[2] = -1;
3274       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
3275       orntNew[3] = ornt[3];
3276       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
3277       orntNew[4] = ornt[4];
3278       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
3279       orntNew[5] = -4;
3280       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
3281       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
3282 #if 1
3283       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
3284       for (p = 0; p < 6; ++p) {
3285         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
3286       }
3287 #endif
3288       /* D hex */
3289       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
3290       orntNew[0] = ornt[0];
3291       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
3292       orntNew[1] = 0;
3293       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
3294       orntNew[2] = ornt[2];
3295       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
3296       orntNew[3] = 0;
3297       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
3298       orntNew[4] = ornt[4];
3299       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
3300       orntNew[5] = -4;
3301       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
3302       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
3303 #if 1
3304       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
3305       for (p = 0; p < 6; ++p) {
3306         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
3307       }
3308 #endif
3309       /* E hex */
3310       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
3311       orntNew[0] = -4;
3312       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
3313       orntNew[1] = ornt[1];
3314       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
3315       orntNew[2] = ornt[2];
3316       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
3317       orntNew[3] = 0;
3318       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
3319       orntNew[4] = -1;
3320       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
3321       orntNew[5] = ornt[5];
3322       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
3323       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
3324 #if 1
3325       if ((newp+4 < cStartNew) || (newp+4 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+4, cStartNew, cEndNew);
3326       for (p = 0; p < 6; ++p) {
3327         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
3328       }
3329 #endif
3330       /* F hex */
3331       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
3332       orntNew[0] = -4;
3333       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
3334       orntNew[1] = ornt[1];
3335       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
3336       orntNew[2] = ornt[2];
3337       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
3338       orntNew[3] = -1;
3339       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
3340       orntNew[4] = ornt[4];
3341       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
3342       orntNew[5] = 1;
3343       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
3344       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
3345 #if 1
3346       if ((newp+5 < cStartNew) || (newp+5 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+5, cStartNew, cEndNew);
3347       for (p = 0; p < 6; ++p) {
3348         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
3349       }
3350 #endif
3351       /* G hex */
3352       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
3353       orntNew[0] = -4;
3354       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
3355       orntNew[1] = ornt[1];
3356       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
3357       orntNew[2] = 0;
3358       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
3359       orntNew[3] = ornt[3];
3360       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
3361       orntNew[4] = ornt[4];
3362       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
3363       orntNew[5] = -3;
3364       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
3365       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
3366 #if 1
3367       if ((newp+6 < cStartNew) || (newp+6 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+6, cStartNew, cEndNew);
3368       for (p = 0; p < 6; ++p) {
3369         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
3370       }
3371 #endif
3372       /* H hex */
3373       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
3374       orntNew[0] = -4;
3375       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
3376       orntNew[1] = ornt[1];
3377       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
3378       orntNew[2] = -1;
3379       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
3380       orntNew[3] = ornt[3];
3381       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
3382       orntNew[4] = 3;
3383       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
3384       orntNew[5] = ornt[5];
3385       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
3386       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
3387 #if 1
3388       if ((newp+7 < cStartNew) || (newp+7 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+7, cStartNew, cEndNew);
3389       for (p = 0; p < 6; ++p) {
3390         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
3391       }
3392 #endif
3393     }
3394     /* Split faces have 4 edges and the same cells as the parent */
3395     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
3396     ierr = PetscMalloc1((4 + maxSupportSize*2), &supportRef);CHKERRQ(ierr);
3397     for (f = fStart; f < fEnd; ++f) {
3398       for (r = 0; r < 4; ++r) {
3399         /* TODO: This can come from GetFaces_Internal() */
3400         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};
3401         const PetscInt  newp = fStartNew + (f - fStart)*4 + r;
3402         const PetscInt *cone, *ornt, *support;
3403         PetscInt        coneNew[4], orntNew[4], coneSize, c, supportSize, s;
3404 
3405         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
3406         ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
3407         coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
3408         orntNew[(r+3)%4] = ornt[(r+3)%4];
3409         coneNew[(r+0)%4] = eStartNew + (cone[r]       - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
3410         orntNew[(r+0)%4] = ornt[r];
3411         coneNew[(r+1)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
3412         orntNew[(r+1)%4] = 0;
3413         coneNew[(r+2)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + (r+3)%4;
3414         orntNew[(r+2)%4] = -2;
3415         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3416         ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3417 #if 1
3418         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3419         for (p = 0; p < 4; ++p) {
3420           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3421         }
3422 #endif
3423         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
3424         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
3425         for (s = 0; s < supportSize; ++s) {
3426           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
3427           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3428           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
3429           for (c = 0; c < coneSize; ++c) {
3430             if (cone[c] == f) break;
3431           }
3432           supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+GetQuadSubfaceInverse_Static(ornt[c], r)];
3433         }
3434         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3435 #if 1
3436         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3437         for (p = 0; p < supportSize; ++p) {
3438           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
3439         }
3440 #endif
3441       }
3442     }
3443     /* Interior faces have 4 edges and 2 cells */
3444     for (c = cStart; c < cEnd; ++c) {
3445       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};
3446       const PetscInt *cone, *ornt;
3447       PetscInt        newp, coneNew[4], orntNew[4], supportNew[2];
3448 
3449       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
3450       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
3451       /* A-D face */
3452       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0;
3453       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
3454       orntNew[0] = 0;
3455       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
3456       orntNew[1] = 0;
3457       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
3458       orntNew[2] = -2;
3459       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
3460       orntNew[3] = -2;
3461       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3462       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3463 #if 1
3464       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3465       for (p = 0; p < 4; ++p) {
3466         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3467       }
3468 #endif
3469       /* C-D face */
3470       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1;
3471       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
3472       orntNew[0] = 0;
3473       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
3474       orntNew[1] = 0;
3475       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
3476       orntNew[2] = -2;
3477       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
3478       orntNew[3] = -2;
3479       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3480       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3481 #if 1
3482       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3483       for (p = 0; p < 4; ++p) {
3484         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3485       }
3486 #endif
3487       /* B-C face */
3488       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2;
3489       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
3490       orntNew[0] = -2;
3491       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
3492       orntNew[1] = 0;
3493       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
3494       orntNew[2] = 0;
3495       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
3496       orntNew[3] = -2;
3497       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3498       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3499 #if 1
3500       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3501       for (p = 0; p < 4; ++p) {
3502         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3503       }
3504 #endif
3505       /* A-B face */
3506       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3;
3507       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
3508       orntNew[0] = -2;
3509       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
3510       orntNew[1] = 0;
3511       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
3512       orntNew[2] = 0;
3513       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
3514       orntNew[3] = -2;
3515       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3516       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3517 #if 1
3518       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3519       for (p = 0; p < 4; ++p) {
3520         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3521       }
3522 #endif
3523       /* E-F face */
3524       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4;
3525       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
3526       orntNew[0] = -2;
3527       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
3528       orntNew[1] = -2;
3529       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
3530       orntNew[2] = 0;
3531       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
3532       orntNew[3] = 0;
3533       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3534       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3535 #if 1
3536       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3537       for (p = 0; p < 4; ++p) {
3538         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3539       }
3540 #endif
3541       /* F-G face */
3542       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5;
3543       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
3544       orntNew[0] = -2;
3545       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
3546       orntNew[1] = -2;
3547       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
3548       orntNew[2] = 0;
3549       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
3550       orntNew[3] = 0;
3551       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3552       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3553 #if 1
3554       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3555       for (p = 0; p < 4; ++p) {
3556         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3557       }
3558 #endif
3559       /* G-H face */
3560       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6;
3561       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
3562       orntNew[0] = -2;
3563       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
3564       orntNew[1] = 0;
3565       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
3566       orntNew[2] = 0;
3567       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
3568       orntNew[3] = -2;
3569       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3570       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3571 #if 1
3572       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3573       for (p = 0; p < 4; ++p) {
3574         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3575       }
3576 #endif
3577       /* E-H face */
3578       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7;
3579       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
3580       orntNew[0] = -2;
3581       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
3582       orntNew[1] = -2;
3583       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
3584       orntNew[2] = 0;
3585       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
3586       orntNew[3] = 0;
3587       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3588       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3589 #if 1
3590       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3591       for (p = 0; p < 4; ++p) {
3592         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3593       }
3594 #endif
3595       /* A-E face */
3596       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8;
3597       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
3598       orntNew[0] = 0;
3599       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
3600       orntNew[1] = 0;
3601       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
3602       orntNew[2] = -2;
3603       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
3604       orntNew[3] = -2;
3605       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3606       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3607 #if 1
3608       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3609       for (p = 0; p < 4; ++p) {
3610         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3611       }
3612 #endif
3613       /* D-F face */
3614       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9;
3615       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
3616       orntNew[0] = -2;
3617       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
3618       orntNew[1] = 0;
3619       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
3620       orntNew[2] = 0;
3621       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
3622       orntNew[3] = -2;
3623       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3624       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3625 #if 1
3626       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3627       for (p = 0; p < 4; ++p) {
3628         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3629       }
3630 #endif
3631       /* C-G face */
3632       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10;
3633       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
3634       orntNew[0] = -2;
3635       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
3636       orntNew[1] = -2;
3637       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
3638       orntNew[2] = 0;
3639       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
3640       orntNew[3] = 0;
3641       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3642       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3643 #if 1
3644       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3645       for (p = 0; p < 4; ++p) {
3646         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3647       }
3648 #endif
3649       /* B-H face */
3650       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11;
3651       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
3652       orntNew[0] = 0;
3653       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
3654       orntNew[1] = -2;
3655       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
3656       orntNew[2] = -2;
3657       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
3658       orntNew[3] = 0;
3659       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3660       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
3661 #if 1
3662       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3663       for (p = 0; p < 4; ++p) {
3664         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3665       }
3666 #endif
3667       for (r = 0; r < 12; ++r) {
3668         newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
3669         supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
3670         supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
3671         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3672 #if 1
3673         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3674         for (p = 0; p < 2; ++p) {
3675           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
3676         }
3677 #endif
3678       }
3679     }
3680     /* Split edges have 2 vertices and the same faces as the parent */
3681     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
3682     for (e = eStart; e < eEnd; ++e) {
3683       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
3684 
3685       for (r = 0; r < 2; ++r) {
3686         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
3687         const PetscInt *cone, *ornt, *support;
3688         PetscInt        coneNew[2], coneSize, c, supportSize, s;
3689 
3690         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
3691         coneNew[0]       = vStartNew + (cone[0] - vStart);
3692         coneNew[1]       = vStartNew + (cone[1] - vStart);
3693         coneNew[(r+1)%2] = newv;
3694         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3695 #if 1
3696         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3697         for (p = 0; p < 2; ++p) {
3698           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
3699         }
3700 #endif
3701         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
3702         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
3703         for (s = 0; s < supportSize; ++s) {
3704           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
3705           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3706           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
3707           for (c = 0; c < coneSize; ++c) {
3708             if (cone[c] == e) break;
3709           }
3710           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
3711         }
3712         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3713 #if 1
3714         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3715         for (p = 0; p < supportSize; ++p) {
3716           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
3717         }
3718 #endif
3719       }
3720     }
3721     /* Face edges have 2 vertices and 2+cells faces */
3722     for (f = fStart; f < fEnd; ++f) {
3723       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};
3724       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
3725       const PetscInt *cone, *coneCell, *orntCell, *support;
3726       PetscInt        coneNew[2], coneSize, c, supportSize, s;
3727 
3728       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
3729       for (r = 0; r < 4; ++r) {
3730         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
3731 
3732         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
3733         coneNew[1] = newv;
3734         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3735 #if 1
3736         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3737         for (p = 0; p < 2; ++p) {
3738           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
3739         }
3740 #endif
3741         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
3742         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
3743         supportRef[0] = fStartNew + (f - fStart)*4 + r;
3744         supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
3745         for (s = 0; s < supportSize; ++s) {
3746           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
3747           ierr = DMPlexGetCone(dm, support[s], &coneCell);CHKERRQ(ierr);
3748           ierr = DMPlexGetConeOrientation(dm, support[s], &orntCell);CHKERRQ(ierr);
3749           for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
3750           supportRef[2+s] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
3751         }
3752         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3753 #if 1
3754         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3755         for (p = 0; p < 2+supportSize; ++p) {
3756           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
3757         }
3758 #endif
3759       }
3760     }
3761     /* Cell edges have 2 vertices and 4 faces */
3762     for (c = cStart; c < cEnd; ++c) {
3763       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};
3764       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
3765       const PetscInt *cone;
3766       PetscInt        coneNew[2], supportNew[4];
3767 
3768       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
3769       for (r = 0; r < 6; ++r) {
3770         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
3771 
3772         coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
3773         coneNew[1] = newv;
3774         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
3775 #if 1
3776         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3777         for (p = 0; p < 2; ++p) {
3778           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
3779         }
3780 #endif
3781         for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
3782         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3783 #if 1
3784         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3785         for (p = 0; p < 4; ++p) {
3786           if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportNew[p], fStartNew, fEndNew);
3787         }
3788 #endif
3789       }
3790     }
3791     /* Old vertices have identical supports */
3792     for (v = vStart; v < vEnd; ++v) {
3793       const PetscInt  newp = vStartNew + (v - vStart);
3794       const PetscInt *support, *cone;
3795       PetscInt        size, s;
3796 
3797       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
3798       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
3799       for (s = 0; s < size; ++s) {
3800         PetscInt r = 0;
3801 
3802         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3803         if (cone[1] == v) r = 1;
3804         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
3805       }
3806       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3807 #if 1
3808       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3809       for (p = 0; p < size; ++p) {
3810         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
3811       }
3812 #endif
3813     }
3814     /* Edge vertices have 2 + faces supports */
3815     for (e = eStart; e < eEnd; ++e) {
3816       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
3817       const PetscInt *cone, *support;
3818       PetscInt        size, s;
3819 
3820       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
3821       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
3822       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
3823       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
3824       for (s = 0; s < size; ++s) {
3825         PetscInt r;
3826 
3827         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3828         for (r = 0; r < 4; ++r) if (cone[r] == e) break;
3829         supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*4 + r;
3830       }
3831       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3832 #if 1
3833       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3834       for (p = 0; p < 2+size; ++p) {
3835         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
3836       }
3837 #endif
3838     }
3839     /* Face vertices have 4 + cells supports */
3840     for (f = fStart; f < fEnd; ++f) {
3841       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
3842       const PetscInt *cone, *support;
3843       PetscInt        size, s;
3844 
3845       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
3846       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
3847       for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eEnd - eStart)*2 +  (f - fStart)*4 + r;
3848       for (s = 0; s < size; ++s) {
3849         PetscInt r;
3850 
3851         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
3852         for (r = 0; r < 6; ++r) if (cone[r] == f) break;
3853         supportRef[4+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (support[s] - cStart)*6 + r;
3854       }
3855       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
3856 #if 1
3857       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3858       for (p = 0; p < 4+size; ++p) {
3859         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
3860       }
3861 #endif
3862     }
3863     /* Cell vertices have 6 supports */
3864     for (c = cStart; c < cEnd; ++c) {
3865       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
3866       PetscInt       supportNew[6];
3867 
3868       for (r = 0; r < 6; ++r) {
3869         supportNew[r] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
3870       }
3871       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
3872     }
3873     ierr = PetscFree(supportRef);CHKERRQ(ierr);
3874     break;
3875   case 8:
3876     /* Hybrid Hex 3D */
3877     ierr = DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);CHKERRQ(ierr);
3878     /*
3879      Bottom (viewed from top)    Top
3880      1---------2---------2       7---------2---------6
3881      |         |         |       |         |         |
3882      |    B    2    C    |       |    H    2    G    |
3883      |         |         |       |         |         |
3884      3----3----0----1----1       3----3----0----1----1
3885      |         |         |       |         |         |
3886      |    A    0    D    |       |    E    0    F    |
3887      |         |         |       |         |         |
3888      0---------0---------3       4---------0---------5
3889      */
3890     /* Interior cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
3891     for (c = cStart; c < cMax; ++c) {
3892       const PetscInt  newp = (c - cStart)*8;
3893       const PetscInt *cone, *ornt;
3894       PetscInt        coneNew[6], orntNew[6];
3895 
3896       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
3897       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
3898       /* A hex */
3899       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
3900       orntNew[0] = ornt[0];
3901       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
3902       orntNew[1] = 0;
3903       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
3904       orntNew[2] = ornt[2];
3905       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
3906       orntNew[3] = 0;
3907       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
3908       orntNew[4] = 0;
3909       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
3910       orntNew[5] = ornt[5];
3911       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
3912       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
3913 #if 1
3914       if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cMaxNew);
3915       for (p = 0; p < 6; ++p) {
3916         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3917       }
3918 #endif
3919       /* B hex */
3920       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
3921       orntNew[0] = ornt[0];
3922       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
3923       orntNew[1] = 0;
3924       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
3925       orntNew[2] = -1;
3926       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
3927       orntNew[3] = ornt[3];
3928       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
3929       orntNew[4] = 0;
3930       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
3931       orntNew[5] = ornt[5];
3932       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
3933       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
3934 #if 1
3935       if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cMaxNew);
3936       for (p = 0; p < 6; ++p) {
3937         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3938       }
3939 #endif
3940       /* C hex */
3941       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
3942       orntNew[0] = ornt[0];
3943       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
3944       orntNew[1] = 0;
3945       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
3946       orntNew[2] = -1;
3947       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
3948       orntNew[3] = ornt[3];
3949       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
3950       orntNew[4] = ornt[4];
3951       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
3952       orntNew[5] = -4;
3953       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
3954       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
3955 #if 1
3956       if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cMaxNew);
3957       for (p = 0; p < 6; ++p) {
3958         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3959       }
3960 #endif
3961       /* D hex */
3962       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
3963       orntNew[0] = ornt[0];
3964       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
3965       orntNew[1] = 0;
3966       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
3967       orntNew[2] = ornt[2];
3968       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
3969       orntNew[3] = 0;
3970       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
3971       orntNew[4] = ornt[4];
3972       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
3973       orntNew[5] = -4;
3974       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
3975       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
3976 #if 1
3977       if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cMaxNew);
3978       for (p = 0; p < 6; ++p) {
3979         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3980       }
3981 #endif
3982       /* E hex */
3983       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
3984       orntNew[0] = -4;
3985       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
3986       orntNew[1] = ornt[1];
3987       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
3988       orntNew[2] = ornt[2];
3989       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
3990       orntNew[3] = 0;
3991       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
3992       orntNew[4] = -1;
3993       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
3994       orntNew[5] = ornt[5];
3995       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
3996       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
3997 #if 1
3998       if ((newp+4 < cStartNew) || (newp+4 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+4, cStartNew, cMaxNew);
3999       for (p = 0; p < 6; ++p) {
4000         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
4001       }
4002 #endif
4003       /* F hex */
4004       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
4005       orntNew[0] = -4;
4006       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
4007       orntNew[1] = ornt[1];
4008       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
4009       orntNew[2] = ornt[2];
4010       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
4011       orntNew[3] = -1;
4012       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
4013       orntNew[4] = ornt[4];
4014       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
4015       orntNew[5] = 1;
4016       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
4017       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
4018 #if 1
4019       if ((newp+5 < cStartNew) || (newp+5 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+5, cStartNew, cMaxNew);
4020       for (p = 0; p < 6; ++p) {
4021         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
4022       }
4023 #endif
4024       /* G hex */
4025       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
4026       orntNew[0] = -4;
4027       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
4028       orntNew[1] = ornt[1];
4029       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
4030       orntNew[2] = 0;
4031       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
4032       orntNew[3] = ornt[3];
4033       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
4034       orntNew[4] = ornt[4];
4035       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
4036       orntNew[5] = -3;
4037       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
4038       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
4039 #if 1
4040       if ((newp+6 < cStartNew) || (newp+6 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+6, cStartNew, cMaxNew);
4041       for (p = 0; p < 6; ++p) {
4042         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
4043       }
4044 #endif
4045       /* H hex */
4046       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
4047       orntNew[0] = -4;
4048       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
4049       orntNew[1] = ornt[1];
4050       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
4051       orntNew[2] = -1;
4052       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
4053       orntNew[3] = ornt[3];
4054       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
4055       orntNew[4] = 3;
4056       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
4057       orntNew[5] = ornt[5];
4058       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
4059       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
4060 #if 1
4061       if ((newp+7 < cStartNew) || (newp+7 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+7, cStartNew, cMaxNew);
4062       for (p = 0; p < 6; ++p) {
4063         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
4064       }
4065 #endif
4066     }
4067     /* Hybrid cells have 6 faces: Front, Back, Sides */
4068     /*
4069      3---------2---------2
4070      |         |         |
4071      |    D    2    C    |
4072      |         |         |
4073      3----3----0----1----1
4074      |         |         |
4075      |    A    0    B    |
4076      |         |         |
4077      0---------0---------1
4078      */
4079     for (c = cMax; c < cEnd; ++c) {
4080       const PetscInt  newp = (cMax - cStart)*8 + (c - cMax)*4;
4081       const PetscInt *cone, *ornt, *fornt;
4082       PetscInt        coneNew[6], orntNew[6];
4083 
4084       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
4085       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
4086       ierr = DMPlexGetConeOrientation(dm, cone[0], &fornt);CHKERRQ(ierr);
4087       for (r = 0; r < 4; ++r) {
4088         PetscInt subfA = GetQuadSubface_Static(ornt[0], r);
4089         PetscInt edgeA = GetQuadEdge_Static(ornt[0], r);
4090         PetscInt edgeB = (edgeA+3)%4;
4091         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]);
4092         coneNew[0]         = fStartNew + (cone[0] - fStart)*4 + subfA;
4093         orntNew[0]         = ornt[0];
4094         coneNew[1]         = fStartNew + (cone[1] - fStart)*4 + subfA;
4095         orntNew[1]         = ornt[0];
4096         coneNew[(r+0)%4+2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[edgeA+2] - fMax)*2 + (fornt[edgeA] < 0 ? 1 : 0);
4097         orntNew[(r+0)%4+2] = ornt[edgeA];
4098         coneNew[(r+1)%4+2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd          - fMax)*2 + (c - cMax)*4 + edgeA;
4099         orntNew[(r+1)%4+2] = 0;
4100         coneNew[(r+2)%4+2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd          - fMax)*2 + (c - cMax)*4 + edgeB;
4101         orntNew[(r+2)%4+2] = -2;
4102         coneNew[(r+3)%4+2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[edgeB+2] - fMax)*2 + (fornt[edgeB] < 0 ? 0 : 1);
4103         orntNew[(r+3)%4+2] = ornt[edgeB];
4104         ierr       = DMPlexSetCone(rdm, newp+r, coneNew);CHKERRQ(ierr);
4105         ierr       = DMPlexSetConeOrientation(rdm, newp+r, orntNew);CHKERRQ(ierr);
4106 #if 1
4107         if ((newp+r < cMaxNew) || (newp+r >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", newp+r, cMaxNew, cEndNew);
4108         for (p = 0; p < 2; ++p) {
4109           if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
4110         }
4111         for (p = 2; p < 6; ++p) {
4112           if ((coneNew[p] < fMaxNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", coneNew[p], fMaxNew, fEndNew);
4113         }
4114 #endif
4115       }
4116     }
4117     /* Interior split faces have 4 edges and the same cells as the parent */
4118     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
4119     ierr = PetscMalloc1((4 + maxSupportSize*2), &supportRef);CHKERRQ(ierr);
4120     for (f = fStart; f < fMax; ++f) {
4121       for (r = 0; r < 4; ++r) {
4122         /* TODO: This can come from GetFaces_Internal() */
4123         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};
4124         const PetscInt  newp = fStartNew + (f - fStart)*4 + r;
4125         const PetscInt *cone, *ornt, *support;
4126         PetscInt        coneNew[4], orntNew[4], coneSize, c, supportSize, s;
4127 
4128         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
4129         ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
4130         coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
4131         orntNew[(r+3)%4] = ornt[(r+3)%4];
4132         coneNew[(r+0)%4] = eStartNew + (cone[r]       - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
4133         orntNew[(r+0)%4] = ornt[r];
4134         coneNew[(r+1)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
4135         orntNew[(r+1)%4] = 0;
4136         coneNew[(r+2)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + (r+3)%4;
4137         orntNew[(r+2)%4] = -2;
4138         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4139         ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4140 #if 1
4141         if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4142         for (p = 0; p < 4; ++p) {
4143           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4144         }
4145 #endif
4146         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
4147         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
4148         for (s = 0; s < supportSize; ++s) {
4149           PetscInt subf;
4150           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
4151           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
4152           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
4153           for (c = 0; c < coneSize; ++c) {
4154             if (cone[c] == f) break;
4155           }
4156           subf = GetQuadSubfaceInverse_Static(ornt[c], r);
4157           if (support[s] < cMax) {
4158             supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+subf];
4159           } else {
4160             supportRef[s] = cStartNew + (cMax       - cStart)*8 + (support[s] - cMax)*4 + subf;
4161           }
4162         }
4163         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4164 #if 1
4165         if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4166         for (p = 0; p < supportSize; ++p) {
4167           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
4168         }
4169 #endif
4170       }
4171     }
4172     /* Interior faces have 4 edges and 2 cells */
4173     for (c = cStart; c < cMax; ++c) {
4174       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};
4175       const PetscInt *cone, *ornt;
4176       PetscInt        newp, coneNew[4], orntNew[4], supportNew[2];
4177 
4178       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
4179       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
4180       /* A-D face */
4181       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 0;
4182       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
4183       orntNew[0] = 0;
4184       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
4185       orntNew[1] = 0;
4186       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
4187       orntNew[2] = -2;
4188       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
4189       orntNew[3] = -2;
4190       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4191       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4192 #if 1
4193       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4194       for (p = 0; p < 4; ++p) {
4195         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4196       }
4197 #endif
4198       /* C-D face */
4199       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 1;
4200       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
4201       orntNew[0] = 0;
4202       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
4203       orntNew[1] = 0;
4204       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
4205       orntNew[2] = -2;
4206       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
4207       orntNew[3] = -2;
4208       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4209       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4210 #if 1
4211       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4212       for (p = 0; p < 4; ++p) {
4213         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4214       }
4215 #endif
4216       /* B-C face */
4217       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 2;
4218       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
4219       orntNew[0] = -2;
4220       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
4221       orntNew[1] = 0;
4222       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
4223       orntNew[2] = 0;
4224       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
4225       orntNew[3] = -2;
4226       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4227       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4228 #if 1
4229       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4230       for (p = 0; p < 4; ++p) {
4231         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4232       }
4233 #endif
4234       /* A-B face */
4235       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 3;
4236       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
4237       orntNew[0] = -2;
4238       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
4239       orntNew[1] = 0;
4240       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
4241       orntNew[2] = 0;
4242       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
4243       orntNew[3] = -2;
4244       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4245       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4246 #if 1
4247       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4248       for (p = 0; p < 4; ++p) {
4249         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4250       }
4251 #endif
4252       /* E-F face */
4253       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 4;
4254       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
4255       orntNew[0] = -2;
4256       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
4257       orntNew[1] = -2;
4258       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
4259       orntNew[2] = 0;
4260       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
4261       orntNew[3] = 0;
4262       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4263       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4264 #if 1
4265       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4266       for (p = 0; p < 4; ++p) {
4267         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4268       }
4269 #endif
4270       /* F-G face */
4271       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 5;
4272       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
4273       orntNew[0] = -2;
4274       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
4275       orntNew[1] = -2;
4276       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
4277       orntNew[2] = 0;
4278       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
4279       orntNew[3] = 0;
4280       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4281       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4282 #if 1
4283       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4284       for (p = 0; p < 4; ++p) {
4285         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4286       }
4287 #endif
4288       /* G-H face */
4289       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 6;
4290       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
4291       orntNew[0] = -2;
4292       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
4293       orntNew[1] = 0;
4294       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
4295       orntNew[2] = 0;
4296       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
4297       orntNew[3] = -2;
4298       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4299       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4300 #if 1
4301       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4302       for (p = 0; p < 4; ++p) {
4303         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4304       }
4305 #endif
4306       /* E-H face */
4307       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 7;
4308       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
4309       orntNew[0] = -2;
4310       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
4311       orntNew[1] = -2;
4312       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
4313       orntNew[2] = 0;
4314       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
4315       orntNew[3] = 0;
4316       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4317       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4318 #if 1
4319       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4320       for (p = 0; p < 4; ++p) {
4321         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4322       }
4323 #endif
4324       /* A-E face */
4325       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 8;
4326       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
4327       orntNew[0] = 0;
4328       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
4329       orntNew[1] = 0;
4330       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
4331       orntNew[2] = -2;
4332       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
4333       orntNew[3] = -2;
4334       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4335       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4336 #if 1
4337       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4338       for (p = 0; p < 4; ++p) {
4339         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4340       }
4341 #endif
4342       /* D-F face */
4343       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 9;
4344       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
4345       orntNew[0] = -2;
4346       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
4347       orntNew[1] = 0;
4348       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
4349       orntNew[2] = 0;
4350       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
4351       orntNew[3] = -2;
4352       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4353       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4354 #if 1
4355       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4356       for (p = 0; p < 4; ++p) {
4357         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4358       }
4359 #endif
4360       /* C-G face */
4361       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 10;
4362       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
4363       orntNew[0] = -2;
4364       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
4365       orntNew[1] = -2;
4366       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
4367       orntNew[2] = 0;
4368       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
4369       orntNew[3] = 0;
4370       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4371       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4372 #if 1
4373       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4374       for (p = 0; p < 4; ++p) {
4375         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4376       }
4377 #endif
4378       /* B-H face */
4379       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 11;
4380       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
4381       orntNew[0] = 0;
4382       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
4383       orntNew[1] = -2;
4384       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
4385       orntNew[2] = -2;
4386       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
4387       orntNew[3] = 0;
4388       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4389       ierr       = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4390 #if 1
4391       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4392       for (p = 0; p < 4; ++p) {
4393         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4394       }
4395 #endif
4396       for (r = 0; r < 12; ++r) {
4397         newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + r;
4398         supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
4399         supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
4400         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4401 #if 1
4402         if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4403         for (p = 0; p < 2; ++p) {
4404           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
4405         }
4406 #endif
4407       }
4408     }
4409     /* Hybrid split faces have 4 edges and same cells */
4410     for (f = fMax; f < fEnd; ++f) {
4411       const PetscInt *cone, *ornt, *support;
4412       PetscInt        coneNew[4], orntNew[4];
4413       PetscInt        supportNew[2], size, s, c;
4414 
4415       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
4416       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
4417       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
4418       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
4419       for (r = 0; r < 2; ++r) {
4420         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + r;
4421 
4422         coneNew[0]   = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
4423         orntNew[0]   = ornt[0];
4424         coneNew[1]   = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
4425         orntNew[1]   = ornt[1];
4426         coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (cone[2+r] - eMax);
4427         orntNew[2+r] = 0;
4428         coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd      - eMax) + (f - fMax);
4429         orntNew[3-r] = 0;
4430         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4431         ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
4432 #if 1
4433         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
4434         for (p = 0; p < 2; ++p) {
4435           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4436         }
4437         for (p = 2; p < 4; ++p) {
4438           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", coneNew[p], eMaxNew, eEndNew);
4439         }
4440 #endif
4441         for (s = 0; s < size; ++s) {
4442           const PetscInt *coneCell, *orntCell, *fornt;
4443 
4444           ierr = DMPlexGetCone(dm, support[s], &coneCell);CHKERRQ(ierr);
4445           ierr = DMPlexGetConeOrientation(dm, support[s], &orntCell);CHKERRQ(ierr);
4446           for (c = 2; c < 6; ++c) if (coneCell[c] == f) break;
4447           if (c >= 6) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of cell %d", f, support[s]);
4448           ierr = DMPlexGetConeOrientation(dm, coneCell[0], &fornt);CHKERRQ(ierr);
4449           supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetQuadEdgeInverse_Static(orntCell[0], c-2) + (fornt[c-2] < 0 ? 1-r : r))%4;
4450         }
4451         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4452 #if 1
4453         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
4454         for (p = 0; p < size; ++p) {
4455           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", supportNew[p], cMaxNew, cEndNew);
4456         }
4457 #endif
4458       }
4459     }
4460     /* Hybrid cell faces have 4 edges and 2 cells */
4461     for (c = cMax; c < cEnd; ++c) {
4462       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4;
4463       const PetscInt *cone, *ornt;
4464       PetscInt        coneNew[4], orntNew[4];
4465       PetscInt        supportNew[2];
4466 
4467       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
4468       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
4469       for (r = 0; r < 4; ++r) {
4470         coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], r);
4471         orntNew[0] = 0;
4472         coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], r);
4473         orntNew[1] = 0;
4474         coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (cone[2+GetQuadEdge_Static(ornt[0], r)] - fMax);
4475         orntNew[2] = 0;
4476         coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd                                   - fMax) + (c - cMax);
4477         orntNew[3] = 0;
4478         ierr = DMPlexSetCone(rdm, newp+r, coneNew);CHKERRQ(ierr);
4479         ierr = DMPlexSetConeOrientation(rdm, newp+r, orntNew);CHKERRQ(ierr);
4480 #if 1
4481         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp+r, fMaxNew, fEndNew);
4482         for (p = 0; p < 2; ++p) {
4483           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
4484         }
4485         for (p = 2; p < 4; ++p) {
4486           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", coneNew[p], eMaxNew, eEndNew);
4487         }
4488 #endif
4489         supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], r);
4490         supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], (r+1)%4);
4491         ierr          = DMPlexSetSupport(rdm, newp+r, supportNew);CHKERRQ(ierr);
4492 #if 1
4493         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp+r, fMaxNew, fEndNew);
4494         for (p = 0; p < 2; ++p) {
4495           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", supportNew[p], cMaxNew, cEndNew);
4496         }
4497 #endif
4498       }
4499     }
4500     /* Interior split edges have 2 vertices and the same faces as the parent */
4501     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
4502     for (e = eStart; e < eMax; ++e) {
4503       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
4504 
4505       for (r = 0; r < 2; ++r) {
4506         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
4507         const PetscInt *cone, *ornt, *support;
4508         PetscInt        coneNew[2], coneSize, c, supportSize, s;
4509 
4510         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
4511         coneNew[0]       = vStartNew + (cone[0] - vStart);
4512         coneNew[1]       = vStartNew + (cone[1] - vStart);
4513         coneNew[(r+1)%2] = newv;
4514         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4515 #if 1
4516         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4517         for (p = 0; p < 2; ++p) {
4518           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4519         }
4520 #endif
4521         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
4522         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
4523         for (s = 0; s < supportSize; ++s) {
4524           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
4525           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
4526           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
4527           for (c = 0; c < coneSize; ++c) {
4528             if (cone[c] == e) break;
4529           }
4530           if (support[s] < fMax) {
4531             supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%4;
4532           } else {
4533             supportRef[s] = fStartNew + (fMax       - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
4534           }
4535         }
4536         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4537 #if 1
4538         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4539         for (p = 0; p < supportSize; ++p) {
4540           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
4541         }
4542 #endif
4543       }
4544     }
4545     /* Interior face edges have 2 vertices and 2+cells faces */
4546     for (f = fStart; f < fMax; ++f) {
4547       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};
4548       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
4549       const PetscInt *cone, *coneCell, *orntCell, *support;
4550       PetscInt        coneNew[2], coneSize, c, supportSize, s;
4551 
4552       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
4553       for (r = 0; r < 4; ++r) {
4554         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
4555 
4556         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
4557         coneNew[1] = newv;
4558         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4559 #if 1
4560         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4561         for (p = 0; p < 2; ++p) {
4562           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4563         }
4564 #endif
4565         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
4566         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
4567         supportRef[0] = fStartNew + (f - fStart)*4 + r;
4568         supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
4569         for (s = 0; s < supportSize; ++s) {
4570           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
4571           ierr = DMPlexGetCone(dm, support[s], &coneCell);CHKERRQ(ierr);
4572           ierr = DMPlexGetConeOrientation(dm, support[s], &orntCell);CHKERRQ(ierr);
4573           for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
4574           if (support[s] < cMax) {
4575             supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
4576           } else {
4577             supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + GetQuadEdgeInverse_Static(orntCell[c], r);
4578           }
4579         }
4580         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4581 #if 1
4582         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4583         for (p = 0; p < 2+supportSize; ++p) {
4584           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
4585         }
4586 #endif
4587       }
4588     }
4589     /* Interior cell edges have 2 vertices and 4 faces */
4590     for (c = cStart; c < cMax; ++c) {
4591       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};
4592       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
4593       const PetscInt *cone;
4594       PetscInt        coneNew[2], supportNew[4];
4595 
4596       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
4597       for (r = 0; r < 6; ++r) {
4598         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
4599 
4600         coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[r] - fStart);
4601         coneNew[1] = newv;
4602         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4603 #if 1
4604         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4605         for (p = 0; p < 2; ++p) {
4606           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4607         }
4608 #endif
4609         for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
4610         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4611 #if 1
4612         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4613         for (p = 0; p < 4; ++p) {
4614           if ((supportNew[p] < fStartNew) || (supportNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportNew[p], fStartNew, fMaxNew);
4615         }
4616 #endif
4617       }
4618     }
4619     /* Hybrid edges have two vertices and the same faces */
4620     for (e = eMax; e < eEnd; ++e) {
4621       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (e - eMax);
4622       const PetscInt *cone, *support, *fcone;
4623       PetscInt        coneNew[2], size, fsize, s;
4624 
4625       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
4626       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
4627       ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
4628       coneNew[0] = vStartNew + (cone[0] - vStart);
4629       coneNew[1] = vStartNew + (cone[1] - vStart);
4630       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4631 #if 1
4632       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4633       for (p = 0; p < 2; ++p) {
4634         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4635       }
4636 #endif
4637       for (s = 0; s < size; ++s) {
4638         ierr = DMPlexGetConeSize(dm, support[s], &fsize);CHKERRQ(ierr);
4639         ierr = DMPlexGetCone(dm, support[s], &fcone);CHKERRQ(ierr);
4640         for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
4641         if ((c < 2) || (c > 3)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge %d not found in cone of face %d", e, support[s]);
4642         supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + c-2;
4643       }
4644       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4645 #if 1
4646       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4647       for (p = 0; p < size; ++p) {
4648         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", supportRef[p], fMaxNew, fEndNew);
4649       }
4650 #endif
4651     }
4652     /* Hybrid face edges have 2 vertices and 2+cells faces */
4653     for (f = fMax; f < fEnd; ++f) {
4654       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
4655       const PetscInt *cone, *support, *ccone, *cornt;
4656       PetscInt        coneNew[2], size, csize, s;
4657 
4658       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
4659       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
4660       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
4661       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
4662       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
4663       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4664 #if 1
4665       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4666       for (p = 0; p < 2; ++p) {
4667         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4668       }
4669 #endif
4670       supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 0;
4671       supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 1;
4672       for (s = 0; s < size; ++s) {
4673         ierr = DMPlexGetConeSize(dm, support[s], &csize);CHKERRQ(ierr);
4674         ierr = DMPlexGetCone(dm, support[s], &ccone);CHKERRQ(ierr);
4675         ierr = DMPlexGetConeOrientation(dm, support[s], &cornt);CHKERRQ(ierr);
4676         for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
4677         if ((c < 2) || (c >= csize)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Hybrid face %d is not in cone of hybrid cell %d", f, support[s]);
4678         supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + GetQuadSubfaceInverse_Static(cornt[0], c-2);
4679       }
4680       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4681 #if 1
4682       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4683       for (p = 0; p < 2+size; ++p) {
4684         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", supportRef[p], fMaxNew, fEndNew);
4685       }
4686 #endif
4687     }
4688     /* Hybrid cell edges have 2 vertices and 4 faces */
4689     for (c = cMax; c < cEnd; ++c) {
4690       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
4691       const PetscInt *cone, *support;
4692       PetscInt        coneNew[2], size;
4693 
4694       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
4695       ierr = DMPlexGetSupportSize(dm, c, &size);CHKERRQ(ierr);
4696       ierr = DMPlexGetSupport(dm, c, &support);CHKERRQ(ierr);
4697       coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[0] - fStart);
4698       coneNew[1] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[1] - fStart);
4699       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
4700 #if 1
4701       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4702       for (p = 0; p < 2; ++p) {
4703         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4704       }
4705 #endif
4706       supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 0;
4707       supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 1;
4708       supportRef[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 2;
4709       supportRef[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 3;
4710       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4711 #if 1
4712       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4713       for (p = 0; p < 4; ++p) {
4714         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", supportRef[p], fMaxNew, fEndNew);
4715       }
4716 #endif
4717     }
4718     /* Interior vertices have identical supports */
4719     for (v = vStart; v < vEnd; ++v) {
4720       const PetscInt  newp = vStartNew + (v - vStart);
4721       const PetscInt *support, *cone;
4722       PetscInt        size, s;
4723 
4724       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
4725       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
4726       for (s = 0; s < size; ++s) {
4727         PetscInt r = 0;
4728 
4729         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
4730         if (cone[1] == v) r = 1;
4731         if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
4732         else                   supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (support[s] - eMax);
4733       }
4734       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4735 #if 1
4736       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4737       for (p = 0; p < size; ++p) {
4738         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
4739       }
4740 #endif
4741     }
4742     /* Interior edge vertices have 2 + faces supports */
4743     for (e = eStart; e < eMax; ++e) {
4744       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
4745       const PetscInt *cone, *support;
4746       PetscInt        size, s;
4747 
4748       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
4749       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
4750       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
4751       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
4752       for (s = 0; s < size; ++s) {
4753         PetscInt r;
4754 
4755         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
4756         for (r = 0; r < 4; ++r) if (cone[r] == e) break;
4757         if (support[s] < fMax) {
4758           supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*4 + r;
4759         } else {
4760           supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (fMax       - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (support[s] - fMax);
4761         }
4762       }
4763       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4764 #if 1
4765       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4766       for (p = 0; p < 2+size; ++p) {
4767         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
4768       }
4769 #endif
4770     }
4771     /* Interior face vertices have 4 + cells supports */
4772     for (f = fStart; f < fMax; ++f) {
4773       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
4774       const PetscInt *cone, *support;
4775       PetscInt        size, s;
4776 
4777       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
4778       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
4779       for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eMax - eStart)*2 +  (f - fStart)*4 + r;
4780       for (s = 0; s < size; ++s) {
4781         PetscInt r;
4782 
4783         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
4784         for (r = 0; r < 6; ++r) if (cone[r] == f) break;
4785         if (support[s] < cMax) {
4786           supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (support[s] - cStart)*6 + r;
4787         } else {
4788           supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax       - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (support[s] - cMax);
4789         }
4790       }
4791       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
4792 #if 1
4793       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4794       for (p = 0; p < 4+size; ++p) {
4795         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
4796       }
4797 #endif
4798     }
4799     /* Cell vertices have 6 supports */
4800     for (c = cStart; c < cMax; ++c) {
4801       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
4802       PetscInt       supportNew[6];
4803 
4804       for (r = 0; r < 6; ++r) {
4805         supportNew[r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
4806       }
4807       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
4808     }
4809     ierr = PetscFree(supportRef);CHKERRQ(ierr);
4810     break;
4811   default:
4812     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
4813   }
4814   PetscFunctionReturn(0);
4815 }
4816 
4817 #undef __FUNCT__
4818 #define __FUNCT__ "CellRefinerSetCoordinates"
4819 static PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
4820 {
4821   PetscSection   coordSection, coordSectionNew;
4822   Vec            coordinates, coordinatesNew;
4823   PetscScalar   *coords, *coordsNew;
4824   const PetscInt numVertices = depthSize ? depthSize[0] : 0;
4825   PetscInt       dim, depth, coordSizeNew, cStart, cEnd, cMax, c, vStart, vStartNew, vEnd, v, eStart, eEnd, eMax, e, fStart, fEnd, fMax, f;
4826   PetscErrorCode ierr;
4827 
4828   PetscFunctionBegin;
4829   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
4830   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
4831   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
4832   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
4833   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
4834   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
4835   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, NULL);CHKERRQ(ierr);
4836   if (refiner) {ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr);}
4837   ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr);
4838   ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
4839   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr);
4840   ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr);
4841   ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr);
4842   ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+numVertices);CHKERRQ(ierr);
4843   if (cMax < 0) cMax = cEnd;
4844   if (fMax < 0) fMax = fEnd;
4845   if (eMax < 0) eMax = eEnd;
4846   /* All vertices have the dim coordinates */
4847   for (v = vStartNew; v < vStartNew+numVertices; ++v) {
4848     ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr);
4849     ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr);
4850   }
4851   ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr);
4852   ierr = DMSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr);
4853   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
4854   ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr);
4855   ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr);
4856   ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr);
4857   ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr);
4858   ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr);
4859   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
4860   ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
4861   switch (refiner) {
4862   case 0: break;
4863   case 6: /* Hex 3D */
4864   case 8: /* Hybrid Hex 3D */
4865     /* Face vertices have the average of corner coordinates */
4866     for (f = fStart; f < fMax; ++f) {
4867       const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
4868       PetscInt      *cone = NULL;
4869       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;
4870 
4871       ierr = DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
4872       for (p = 0; p < closureSize*2; p += 2) {
4873         const PetscInt point = cone[p];
4874         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
4875       }
4876       for (v = 0; v < coneSize; ++v) {
4877         ierr = PetscSectionGetOffset(coordSection, cone[v], &off[v]);CHKERRQ(ierr);
4878       }
4879       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
4880       for (d = 0; d < dim; ++d) {
4881         coordsNew[offnew+d] = 0.0;
4882         for (v = 0; v < coneSize; ++v) coordsNew[offnew+d] += coords[off[v]+d];
4883         coordsNew[offnew+d] /= coneSize;
4884       }
4885       ierr = DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
4886     }
4887   case 2: /* Hex 2D */
4888     /* Cell vertices have the average of corner coordinates */
4889     for (c = cStart; c < cMax; ++c) {
4890       const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (c - cStart) + (dim > 2 ? (fMax - fStart) : 0);
4891       PetscInt      *cone = NULL;
4892       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;
4893 
4894       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
4895       for (p = 0; p < closureSize*2; p += 2) {
4896         const PetscInt point = cone[p];
4897         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
4898       }
4899       for (v = 0; v < coneSize; ++v) {
4900         ierr = PetscSectionGetOffset(coordSection, cone[v], &off[v]);CHKERRQ(ierr);
4901       }
4902       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
4903       for (d = 0; d < dim; ++d) {
4904         coordsNew[offnew+d] = 0.0;
4905         for (v = 0; v < coneSize; ++v) coordsNew[offnew+d] += coords[off[v]+d];
4906         coordsNew[offnew+d] /= coneSize;
4907       }
4908       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
4909     }
4910   case 1: /* Simplicial 2D */
4911   case 3: /* Hybrid Simplicial 2D */
4912   case 5: /* Simplicial 3D */
4913   case 7: /* Hybrid Simplicial 3D */
4914     /* Edge vertices have the average of endpoint coordinates */
4915     for (e = eStart; e < eMax; ++e) {
4916       const PetscInt  newv = vStartNew + (vEnd - vStart) + (e - eStart);
4917       const PetscInt *cone;
4918       PetscInt        coneSize, offA, offB, offnew, d;
4919 
4920       ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr);
4921       if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize);
4922       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
4923       ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
4924       ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
4925       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
4926       for (d = 0; d < dim; ++d) {
4927         coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]);
4928       }
4929     }
4930     /* Old vertices have the same coordinates */
4931     for (v = vStart; v < vEnd; ++v) {
4932       const PetscInt newv = vStartNew + (v - vStart);
4933       PetscInt       off, offnew, d;
4934 
4935       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
4936       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
4937       for (d = 0; d < dim; ++d) {
4938         coordsNew[offnew+d] = coords[off+d];
4939       }
4940     }
4941     break;
4942   default:
4943     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
4944   }
4945   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
4946   ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
4947   ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr);
4948   ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr);
4949   ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr);
4950   PetscFunctionReturn(0);
4951 }
4952 
4953 #undef __FUNCT__
4954 #define __FUNCT__ "DMPlexCreateProcessSF"
4955 static PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
4956 {
4957   PetscInt           numRoots, numLeaves, l;
4958   const PetscInt    *localPoints;
4959   const PetscSFNode *remotePoints;
4960   PetscInt          *localPointsNew;
4961   PetscSFNode       *remotePointsNew;
4962   PetscInt          *ranks, *ranksNew;
4963   PetscErrorCode     ierr;
4964 
4965   PetscFunctionBegin;
4966   ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
4967   ierr = PetscMalloc1(numLeaves, &ranks);CHKERRQ(ierr);
4968   for (l = 0; l < numLeaves; ++l) {
4969     ranks[l] = remotePoints[l].rank;
4970   }
4971   ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr);
4972   ierr = PetscMalloc1(numLeaves,    &ranksNew);CHKERRQ(ierr);
4973   ierr = PetscMalloc1(numLeaves,    &localPointsNew);CHKERRQ(ierr);
4974   ierr = PetscMalloc1(numLeaves, &remotePointsNew);CHKERRQ(ierr);
4975   for (l = 0; l < numLeaves; ++l) {
4976     ranksNew[l]              = ranks[l];
4977     localPointsNew[l]        = l;
4978     remotePointsNew[l].index = 0;
4979     remotePointsNew[l].rank  = ranksNew[l];
4980   }
4981   ierr = PetscFree(ranks);CHKERRQ(ierr);
4982   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);
4983   ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr);
4984   ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr);
4985   ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
4986   PetscFunctionReturn(0);
4987 }
4988 
4989 #undef __FUNCT__
4990 #define __FUNCT__ "CellRefinerCreateSF"
4991 static PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
4992 {
4993   PetscSF            sf, sfNew, sfProcess;
4994   IS                 processRanks;
4995   MPI_Datatype       depthType;
4996   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
4997   const PetscInt    *localPoints, *neighbors;
4998   const PetscSFNode *remotePoints;
4999   PetscInt          *localPointsNew;
5000   PetscSFNode       *remotePointsNew;
5001   PetscInt          *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
5002   PetscInt           depth, numNeighbors, pStartNew, pEndNew, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r, n;
5003   PetscInt           cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
5004   PetscErrorCode     ierr;
5005 
5006   PetscFunctionBegin;
5007   ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr);
5008   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
5009   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
5010   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
5011   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
5012   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
5013   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
5014   if (refiner) {ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);}
5015   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
5016   ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr);
5017   /* Caculate size of new SF */
5018   ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
5019   if (numRoots < 0) PetscFunctionReturn(0);
5020   for (l = 0; l < numLeaves; ++l) {
5021     const PetscInt p = localPoints[l];
5022 
5023     switch (refiner) {
5024     case 1:
5025       /* Simplicial 2D */
5026       if ((p >= vStart) && (p < vEnd)) {
5027         /* Old vertices stay the same */
5028         ++numLeavesNew;
5029       } else if ((p >= fStart) && (p < fEnd)) {
5030         /* Old faces add new faces and vertex */
5031         numLeavesNew += 2 + 1;
5032       } else if ((p >= cStart) && (p < cEnd)) {
5033         /* Old cells add new cells and interior faces */
5034         numLeavesNew += 4 + 3;
5035       }
5036       break;
5037     case 2:
5038       /* Hex 2D */
5039       if ((p >= vStart) && (p < vEnd)) {
5040         /* Old vertices stay the same */
5041         ++numLeavesNew;
5042       } else if ((p >= fStart) && (p < fEnd)) {
5043         /* Old faces add new faces and vertex */
5044         numLeavesNew += 2 + 1;
5045       } else if ((p >= cStart) && (p < cEnd)) {
5046         /* Old cells add new cells, interior faces, and vertex */
5047         numLeavesNew += 4 + 4 + 1;
5048       }
5049       break;
5050     case 5:
5051       /* Simplicial 3D */
5052       if ((p >= vStart) && (p < vEnd)) {
5053         /* Old vertices stay the same */
5054         ++numLeavesNew;
5055       } else if ((p >= eStart) && (p < eEnd)) {
5056         /* Old edges add new edges and vertex */
5057         numLeavesNew += 2 + 1;
5058       } else if ((p >= fStart) && (p < fEnd)) {
5059         /* Old faces add new faces and face edges */
5060         numLeavesNew += 4 + 3;
5061       } else if ((p >= cStart) && (p < cEnd)) {
5062         /* Old cells add new cells and interior faces and edges */
5063         numLeavesNew += 8 + 8 + 1;
5064       }
5065       break;
5066     case 7:
5067       /* Hybrid Simplicial 3D */
5068       if ((p >= vStart) && (p < vEnd)) {
5069         /* Interior vertices stay the same */
5070         ++numLeavesNew;
5071       } else if ((p >= eStart) && (p < eMax)) {
5072         /* Interior edges add new edges and vertex */
5073         numLeavesNew += 2 + 1;
5074       } else if ((p >= eMax) && (p < eEnd)) {
5075         /* Hybrid edges stay the same */
5076         ++numLeavesNew;
5077       } else if ((p >= fStart) && (p < fMax)) {
5078         /* Interior faces add new faces and edges */
5079         numLeavesNew += 4 + 3;
5080       } else if ((p >= fMax) && (p < fEnd)) {
5081         /* Hybrid faces add new faces and edges */
5082         numLeavesNew += 2 + 1;
5083       } else if ((p >= cStart) && (p < cMax)) {
5084         /* Interior cells add new cells, faces, and edges */
5085         numLeavesNew += 8 + 8 + 1;
5086       } else if ((p >= cMax) && (p < cEnd)) {
5087         /* Hybrid cells add new cells and faces */
5088         numLeavesNew += 4 + 3;
5089       }
5090       break;
5091     case 6:
5092       /* Hex 3D */
5093       if ((p >= vStart) && (p < vEnd)) {
5094         /* Old vertices stay the same */
5095         ++numLeavesNew;
5096       } else if ((p >= eStart) && (p < eEnd)) {
5097         /* Old edges add new edges, and vertex */
5098         numLeavesNew += 2 + 1;
5099       } else if ((p >= fStart) && (p < fEnd)) {
5100         /* Old faces add new faces, edges, and vertex */
5101         numLeavesNew += 4 + 4 + 1;
5102       } else if ((p >= cStart) && (p < cEnd)) {
5103         /* Old cells add new cells, faces, edges, and vertex */
5104         numLeavesNew += 8 + 12 + 6 + 1;
5105       }
5106       break;
5107     case 8:
5108       /* Hybrid Hex 3D */
5109       if ((p >= vStart) && (p < vEnd)) {
5110         /* Old vertices stay the same */
5111         ++numLeavesNew;
5112       } else if ((p >= eStart) && (p < eMax)) {
5113         /* Interior edges add new edges, and vertex */
5114         numLeavesNew += 2 + 1;
5115       } else if ((p >= eMax) && (p < eEnd)) {
5116         /* Hybrid edges stay the same */
5117         ++numLeavesNew;
5118       } else if ((p >= fStart) && (p < fMax)) {
5119         /* Interior faces add new faces, edges, and vertex */
5120         numLeavesNew += 4 + 4 + 1;
5121       } else if ((p >= fMax) && (p < fEnd)) {
5122         /* Hybrid faces add new faces and edges */
5123         numLeavesNew += 2 + 1;
5124       } else if ((p >= cStart) && (p < cMax)) {
5125         /* Interior cells add new cells, faces, edges, and vertex */
5126         numLeavesNew += 8 + 12 + 6 + 1;
5127       } else if ((p >= cStart) && (p < cEnd)) {
5128         /* Hybrid cells add new cells, faces, and edges */
5129         numLeavesNew += 4 + 4 + 1;
5130       }
5131       break;
5132     default:
5133       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5134     }
5135   }
5136   /* Communicate depthSizes for each remote rank */
5137   ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr);
5138   ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr);
5139   ierr = PetscMalloc5((depth+1)*numNeighbors,&rdepthSize,numNeighbors,&rvStartNew,numNeighbors,&reStartNew,numNeighbors,&rfStartNew,numNeighbors,&rcStartNew);CHKERRQ(ierr);
5140   ierr = PetscMalloc7(depth+1,&depthSizeOld,(depth+1)*numNeighbors,&rdepthSizeOld,(depth+1)*numNeighbors,&rdepthMaxOld,numNeighbors,&rvStart,numNeighbors,&reStart,numNeighbors,&rfStart,numNeighbors,&rcStart);CHKERRQ(ierr);
5141   ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr);
5142   ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr);
5143   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
5144   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
5145   for (n = 0; n < numNeighbors; ++n) {
5146     ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr);
5147   }
5148   depthSizeOld[depth]   = cMax;
5149   depthSizeOld[0]       = vMax;
5150   depthSizeOld[depth-1] = fMax;
5151   depthSizeOld[1]       = eMax;
5152 
5153   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
5154   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
5155 
5156   depthSizeOld[depth]   = cEnd - cStart;
5157   depthSizeOld[0]       = vEnd - vStart;
5158   depthSizeOld[depth-1] = fEnd - fStart;
5159   depthSizeOld[1]       = eEnd - eStart;
5160 
5161   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
5162   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
5163   for (n = 0; n < numNeighbors; ++n) {
5164     ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr);
5165   }
5166   ierr = MPI_Type_free(&depthType);CHKERRQ(ierr);
5167   ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr);
5168   /* Calculate new point SF */
5169   ierr = PetscMalloc1(numLeavesNew,    &localPointsNew);CHKERRQ(ierr);
5170   ierr = PetscMalloc1(numLeavesNew, &remotePointsNew);CHKERRQ(ierr);
5171   ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr);
5172   for (l = 0, m = 0; l < numLeaves; ++l) {
5173     PetscInt    p     = localPoints[l];
5174     PetscInt    rp    = remotePoints[l].index, n;
5175     PetscMPIInt rrank = remotePoints[l].rank;
5176 
5177     ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr);
5178     if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank);
5179     switch (refiner) {
5180     case 1:
5181       /* Simplicial 2D */
5182       if ((p >= vStart) && (p < vEnd)) {
5183         /* Old vertices stay the same */
5184         localPointsNew[m]        = vStartNew     + (p  - vStart);
5185         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5186         remotePointsNew[m].rank  = rrank;
5187         ++m;
5188       } else if ((p >= fStart) && (p < fEnd)) {
5189         /* Old faces add new faces and vertex */
5190         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
5191         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
5192         remotePointsNew[m].rank  = rrank;
5193         ++m;
5194         for (r = 0; r < 2; ++r, ++m) {
5195           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
5196           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
5197           remotePointsNew[m].rank  = rrank;
5198         }
5199       } else if ((p >= cStart) && (p < cEnd)) {
5200         /* Old cells add new cells and interior faces */
5201         for (r = 0; r < 4; ++r, ++m) {
5202           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
5203           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5204           remotePointsNew[m].rank  = rrank;
5205         }
5206         for (r = 0; r < 3; ++r, ++m) {
5207           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*3     + r;
5208           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r;
5209           remotePointsNew[m].rank  = rrank;
5210         }
5211       }
5212       break;
5213     case 2:
5214       /* Hex 2D */
5215       if ((p >= vStart) && (p < vEnd)) {
5216         /* Old vertices stay the same */
5217         localPointsNew[m]        = vStartNew     + (p  - vStart);
5218         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5219         remotePointsNew[m].rank  = rrank;
5220         ++m;
5221       } else if ((p >= fStart) && (p < fEnd)) {
5222         /* Old faces add new faces and vertex */
5223         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
5224         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
5225         remotePointsNew[m].rank  = rrank;
5226         ++m;
5227         for (r = 0; r < 2; ++r, ++m) {
5228           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
5229           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
5230           remotePointsNew[m].rank  = rrank;
5231         }
5232       } else if ((p >= cStart) && (p < cEnd)) {
5233         /* Old cells add new cells, interior faces, and vertex */
5234         for (r = 0; r < 4; ++r, ++m) {
5235           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
5236           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5237           remotePointsNew[m].rank  = rrank;
5238         }
5239         for (r = 0; r < 4; ++r, ++m) {
5240           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*4     + r;
5241           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r;
5242           remotePointsNew[m].rank  = rrank;
5243         }
5244         for (r = 0; r < 1; ++r, ++m) {
5245           localPointsNew[m]        = vStartNew     + (vEnd - vStart)               + (fEnd - fStart)                    + (p  - cStart)     + r;
5246           remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0]  + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]) + r;
5247           remotePointsNew[m].rank  = rrank;
5248         }
5249       }
5250       break;
5251     case 3:
5252       /* Hybrid simplicial 2D */
5253       if ((p >= vStart) && (p < vEnd)) {
5254         /* Old vertices stay the same */
5255         localPointsNew[m]        = vStartNew     + (p  - vStart);
5256         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5257         remotePointsNew[m].rank  = rrank;
5258         ++m;
5259       } else if ((p >= fStart) && (p < fMax)) {
5260         /* Old interior faces add new faces and vertex */
5261         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
5262         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
5263         remotePointsNew[m].rank  = rrank;
5264         ++m;
5265         for (r = 0; r < 2; ++r, ++m) {
5266           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
5267           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
5268           remotePointsNew[m].rank  = rrank;
5269         }
5270       } else if ((p >= fMax) && (p < fEnd)) {
5271         /* Old hybrid faces stay the same */
5272         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - fMax);
5273         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
5274         remotePointsNew[m].rank  = rrank;
5275         ++m;
5276       } else if ((p >= cStart) && (p < cMax)) {
5277         /* Old interior cells add new cells and interior faces */
5278         for (r = 0; r < 4; ++r, ++m) {
5279           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
5280           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5281           remotePointsNew[m].rank  = rrank;
5282         }
5283         for (r = 0; r < 3; ++r, ++m) {
5284           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - cStart)*3     + r;
5285           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r;
5286           remotePointsNew[m].rank  = rrank;
5287         }
5288       } else if ((p >= cStart) && (p < cMax)) {
5289         /* Old hybrid cells add new cells and hybrid face */
5290         for (r = 0; r < 2; ++r, ++m) {
5291           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
5292           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5293           remotePointsNew[m].rank  = rrank;
5294         }
5295         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (cMax                            - cStart)*3     + (p  - cMax);
5296         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]);
5297         remotePointsNew[m].rank  = rrank;
5298         ++m;
5299       }
5300       break;
5301     case 5:
5302       /* Simplicial 3D */
5303       if ((p >= vStart) && (p < vEnd)) {
5304         /* Old vertices stay the same */
5305         localPointsNew[m]        = vStartNew     + (p  - vStart);
5306         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5307         remotePointsNew[m].rank  = rrank;
5308         ++m;
5309       } else if ((p >= eStart) && (p < eEnd)) {
5310         /* Old edges add new edges and vertex */
5311         for (r = 0; r < 2; ++r, ++m) {
5312           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
5313           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
5314           remotePointsNew[m].rank  = rrank;
5315         }
5316         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
5317         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
5318         remotePointsNew[m].rank  = rrank;
5319         ++m;
5320       } else if ((p >= fStart) && (p < fEnd)) {
5321         /* Old faces add new faces and face edges */
5322         for (r = 0; r < 4; ++r, ++m) {
5323           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
5324           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
5325           remotePointsNew[m].rank  = rrank;
5326         }
5327         for (r = 0; r < 3; ++r, ++m) {
5328           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (p  - fStart)*3     + r;
5329           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + (rp - rfStart[n])*3 + r;
5330           remotePointsNew[m].rank  = rrank;
5331         }
5332       } else if ((p >= cStart) && (p < cEnd)) {
5333         /* Old cells add new cells and interior faces and edges */
5334         for (r = 0; r < 8; ++r, ++m) {
5335           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
5336           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
5337           remotePointsNew[m].rank  = rrank;
5338         }
5339         for (r = 0; r < 8; ++r, ++m) {
5340           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*4                    + (p  - cStart)*8     + r;
5341           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*8 + r;
5342           remotePointsNew[m].rank  = rrank;
5343         }
5344         for (r = 0; r < 1; ++r, ++m) {
5345           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (fEnd - fStart)*3                    + (p  - cStart)*1     + r;
5346           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + rdepthSizeOld[n*(depth+1)+depth-1]*3 + (rp - rcStart[n])*1 + r;
5347           remotePointsNew[m].rank  = rrank;
5348         }
5349       }
5350       break;
5351     case 7:
5352       /* Hybrid Simplicial 3D */
5353       if ((p >= vStart) && (p < vEnd)) {
5354         /* Interior vertices stay the same */
5355         localPointsNew[m]        = vStartNew     + (p  - vStart);
5356         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5357         remotePointsNew[m].rank  = rrank;
5358         ++m;
5359       } else if ((p >= eStart) && (p < eMax)) {
5360         /* Interior edges add new edges and vertex */
5361         for (r = 0; r < 2; ++r, ++m) {
5362           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
5363           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
5364           remotePointsNew[m].rank  = rrank;
5365         }
5366         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
5367         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
5368         remotePointsNew[m].rank  = rrank;
5369         ++m;
5370       } else if ((p >= eMax) && (p < eEnd)) {
5371         /* Hybrid edges stay the same */
5372         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (cMax                            - cStart)     + (p  - eMax);
5373         remotePointsNew[m].index = rvStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*3 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n]) + (rp - rdepthMaxOld[n*(depth+1)+1]);
5374         remotePointsNew[m].rank  = rrank;
5375         ++m;
5376       } else if ((p >= fStart) && (p < fMax)) {
5377         /* Interior faces add new faces and edges */
5378         for (r = 0; r < 4; ++r, ++m) {
5379           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
5380           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
5381           remotePointsNew[m].rank  = rrank;
5382         }
5383         for (r = 0; r < 3; ++r, ++m) {
5384           localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (p  - fStart)*3     + r;
5385           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*3 + r;
5386           remotePointsNew[m].rank  = rrank;
5387         }
5388       } else if ((p >= fMax) && (p < fEnd)) {
5389         /* Hybrid faces add new faces and edges */
5390         for (r = 0; r < 2; ++r, ++m) {
5391           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (p  - fMax)*2                              + r;
5392           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;
5393           remotePointsNew[m].rank  = rrank;
5394         }
5395         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (cMax                            - cStart)     + (p  - fMax);
5396         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)+depth-1]);
5397         remotePointsNew[m].rank  = rrank;
5398         ++m;
5399       } else if ((p >= cStart) && (p < cMax)) {
5400         /* Interior cells add new cells, faces, and edges */
5401         for (r = 0; r < 8; ++r, ++m) {
5402           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
5403           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
5404           remotePointsNew[m].rank  = rrank;
5405         }
5406         for (r = 0; r < 8; ++r, ++m) {
5407           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (p  - cStart)*8     + r;
5408           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*8 + r;
5409           remotePointsNew[m].rank  = rrank;
5410         }
5411         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (p  - cStart)*1     + r;
5412         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*3 + (rp - rcStart[n])*1 + r;
5413         remotePointsNew[m].rank  = rrank;
5414         ++m;
5415       } else if ((p >= cMax) && (p < cEnd)) {
5416         /* Hybrid cells add new cells and faces */
5417         for (r = 0; r < 4; ++r, ++m) {
5418           localPointsNew[m]        = cStartNew     + (cMax                            - cStart)*8     + (p  - cMax)*4                            + r;
5419           remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
5420           remotePointsNew[m].rank  = rrank;
5421         }
5422         for (r = 0; r < 3; ++r, ++m) {
5423           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (fEnd                                          - fMax)*2                              + (p  - cMax)*3                            + r;
5424           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;
5425           remotePointsNew[m].rank  = rrank;
5426         }
5427       }
5428       break;
5429     case 6:
5430       /* Hex 3D */
5431       if ((p >= vStart) && (p < vEnd)) {
5432         /* Old vertices stay the same */
5433         localPointsNew[m]        = vStartNew     + (p  - vStart);
5434         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5435         remotePointsNew[m].rank  = rrank;
5436         ++m;
5437       } else if ((p >= eStart) && (p < eEnd)) {
5438         /* Old edges add new edges and vertex */
5439         for (r = 0; r < 2; ++r, ++m) {
5440           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
5441           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
5442           remotePointsNew[m].rank  = rrank;
5443         }
5444         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
5445         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
5446         remotePointsNew[m].rank  = rrank;
5447         ++m;
5448       } else if ((p >= fStart) && (p < fEnd)) {
5449         /* Old faces add new faces, edges, and vertex */
5450         for (r = 0; r < 4; ++r, ++m) {
5451           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
5452           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
5453           remotePointsNew[m].rank  = rrank;
5454         }
5455         for (r = 0; r < 4; ++r, ++m) {
5456           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (p  - fStart)*4     + r;
5457           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + (rp - rfStart[n])*4 + r;
5458           remotePointsNew[m].rank  = rrank;
5459         }
5460         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (eEnd - eStart)              + (p  - fStart);
5461         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+1] + (rp - rfStart[n]);
5462         remotePointsNew[m].rank  = rrank;
5463         ++m;
5464       } else if ((p >= cStart) && (p < cEnd)) {
5465         /* Old cells add new cells, faces, edges, and vertex */
5466         for (r = 0; r < 8; ++r, ++m) {
5467           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
5468           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
5469           remotePointsNew[m].rank  = rrank;
5470         }
5471         for (r = 0; r < 12; ++r, ++m) {
5472           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*4                    + (p  - cStart)*12     + r;
5473           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*12 + r;
5474           remotePointsNew[m].rank  = rrank;
5475         }
5476         for (r = 0; r < 6; ++r, ++m) {
5477           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (fEnd - fStart)*4                    + (p  - cStart)*6     + r;
5478           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*6 + r;
5479           remotePointsNew[m].rank  = rrank;
5480         }
5481         for (r = 0; r < 1; ++r, ++m) {
5482           localPointsNew[m]        = vStartNew     + (eEnd - eStart)              + (fEnd - fStart)                    + (p  - cStart)     + r;
5483           remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+1] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]) + r;
5484           remotePointsNew[m].rank  = rrank;
5485         }
5486       }
5487       break;
5488     case 8:
5489       /* Hybrid Hex 3D */
5490       if ((p >= vStart) && (p < vEnd)) {
5491         /* Interior vertices stay the same */
5492         localPointsNew[m]        = vStartNew     + (p  - vStart);
5493         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5494         remotePointsNew[m].rank  = rrank;
5495         ++m;
5496       } else if ((p >= eStart) && (p < eMax)) {
5497         /* Interior edges add new edges and vertex */
5498         for (r = 0; r < 2; ++r, ++m) {
5499           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
5500           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
5501           remotePointsNew[m].rank  = rrank;
5502         }
5503         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
5504         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
5505         remotePointsNew[m].rank  = rrank;
5506         ++m;
5507       } else if ((p >= eMax) && (p < eEnd)) {
5508         /* Hybrid edges stay the same */
5509         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (cMax                            - cStart)*6     + (p  - eMax);
5510         remotePointsNew[m].index = rvStartNew[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]);
5511         remotePointsNew[m].rank  = rrank;
5512         ++m;
5513       } else if ((p >= fStart) && (p < fMax)) {
5514         /* Interior faces add new faces, edges, and vertex */
5515         for (r = 0; r < 4; ++r, ++m) {
5516           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
5517           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
5518           remotePointsNew[m].rank  = rrank;
5519         }
5520         for (r = 0; r < 4; ++r, ++m) {
5521           localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (p  - fStart)*4     + r;
5522           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*4 + r;
5523           remotePointsNew[m].rank  = rrank;
5524         }
5525         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (eMax                        - eStart)     + (p  - fStart);
5526         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rp - rfStart[n]);
5527         remotePointsNew[m].rank  = rrank;
5528         ++m;
5529       } else if ((p >= fMax) && (p < fEnd)) {
5530         /* Hybrid faces add new faces and edges */
5531         for (r = 0; r < 2; ++r, ++m) {
5532           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (p  - fMax)*2                              + r;
5533           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;
5534           remotePointsNew[m].rank  = rrank;
5535         }
5536         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (cMax                            - cStart)*6     + (fEnd                                          - fMax);
5537         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)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1]);
5538         remotePointsNew[m].rank  = rrank;
5539         ++m;
5540       } else if ((p >= cStart) && (p < cMax)) {
5541         /* Interior cells add new cells, faces, edges, and vertex */
5542         for (r = 0; r < 8; ++r, ++m) {
5543           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
5544           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
5545           remotePointsNew[m].rank  = rrank;
5546         }
5547         for (r = 0; r < 12; ++r, ++m) {
5548           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (p  - cStart)*12     + r;
5549           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*12 + r;
5550           remotePointsNew[m].rank  = rrank;
5551         }
5552         for (r = 0; r < 6; ++r, ++m) {
5553           localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (p  - cStart)*6     + r;
5554           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;
5555           remotePointsNew[m].rank  = rrank;
5556         }
5557         for (r = 0; r < 1; ++r, ++m) {
5558           localPointsNew[m]        = vStartNew     + (eMax                        - eStart)     + (fMax                              - fStart)     + (p  - cStart)     + r;
5559           remotePointsNew[m].index = rvStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]) + r;
5560           remotePointsNew[m].rank  = rrank;
5561         }
5562       } else if ((p >= cMax) && (p < cEnd)) {
5563         /* Hybrid cells add new cells, faces, and edges */
5564         for (r = 0; r < 4; ++r, ++m) {
5565           localPointsNew[m]        = cStartNew     + (cMax                            - cStart)*8     + (p  - cMax)*4                            + r;
5566           remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
5567           remotePointsNew[m].rank  = rrank;
5568         }
5569         for (r = 0; r < 4; ++r, ++m) {
5570           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (fEnd                                          - fMax)*2                              + (p  - cMax)*4                            + r;
5571           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])*4 + r;
5572           remotePointsNew[m].rank  = rrank;
5573         }
5574         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (cMax                            - cStart)*6     + (fEnd                                          - fMax)                              + (p  - cMax);
5575         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)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1]) + (rp - rdepthMaxOld[n*(depth+1)+depth]);
5576         remotePointsNew[m].rank  = rrank;
5577         ++m;
5578       }
5579       break;
5580     default:
5581       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5582     }
5583   }
5584   if (m != numLeavesNew) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of leaf point %d should be %d", m, numLeavesNew);
5585   ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr);
5586   ierr = ISDestroy(&processRanks);CHKERRQ(ierr);
5587   ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
5588   ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr);
5589   ierr = PetscFree7(depthSizeOld,rdepthSizeOld,rdepthMaxOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr);
5590   PetscFunctionReturn(0);
5591 }
5592 
5593 #undef __FUNCT__
5594 #define __FUNCT__ "CellRefinerCreateLabels"
5595 static PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
5596 {
5597   PetscInt       numLabels, l;
5598   PetscInt       depth, newp, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r;
5599   PetscInt       cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
5600   PetscErrorCode ierr;
5601 
5602   PetscFunctionBegin;
5603   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
5604   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
5605   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
5606   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
5607   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
5608   if (refiner) {ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);}
5609   ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
5610   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
5611   switch (refiner) {
5612   case 0: break;
5613   case 7:
5614   case 8:
5615     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
5616   case 3:
5617   case 4:
5618     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
5619     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
5620   }
5621   for (l = 0; l < numLabels; ++l) {
5622     DMLabel         label, labelNew;
5623     const char     *lname;
5624     PetscBool       isDepth;
5625     IS              valueIS;
5626     const PetscInt *values;
5627     PetscInt        numValues, val;
5628 
5629     ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr);
5630     ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr);
5631     if (isDepth) continue;
5632     ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr);
5633     ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr);
5634     ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr);
5635     ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
5636     ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr);
5637     ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
5638     for (val = 0; val < numValues; ++val) {
5639       IS              pointIS;
5640       const PetscInt *points;
5641       PetscInt        numPoints, n;
5642 
5643       ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr);
5644       ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
5645       ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
5646       for (n = 0; n < numPoints; ++n) {
5647         const PetscInt p = points[n];
5648         switch (refiner) {
5649         case 1:
5650           /* Simplicial 2D */
5651           if ((p >= vStart) && (p < vEnd)) {
5652             /* Old vertices stay the same */
5653             newp = vStartNew + (p - vStart);
5654             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5655           } else if ((p >= fStart) && (p < fEnd)) {
5656             /* Old faces add new faces and vertex */
5657             newp = vStartNew + (vEnd - vStart) + (p - fStart);
5658             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5659             for (r = 0; r < 2; ++r) {
5660               newp = fStartNew + (p - fStart)*2 + r;
5661               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5662             }
5663           } else if ((p >= cStart) && (p < cEnd)) {
5664             /* Old cells add new cells and interior faces */
5665             for (r = 0; r < 4; ++r) {
5666               newp = cStartNew + (p - cStart)*4 + r;
5667               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5668             }
5669             for (r = 0; r < 3; ++r) {
5670               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
5671               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5672             }
5673           }
5674           break;
5675         case 2:
5676           /* Hex 2D */
5677           if ((p >= vStart) && (p < vEnd)) {
5678             /* Old vertices stay the same */
5679             newp = vStartNew + (p - vStart);
5680             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5681           } else if ((p >= fStart) && (p < fEnd)) {
5682             /* Old faces add new faces and vertex */
5683             newp = vStartNew + (vEnd - vStart) + (p - fStart);
5684             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5685             for (r = 0; r < 2; ++r) {
5686               newp = fStartNew + (p - fStart)*2 + r;
5687               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5688             }
5689           } else if ((p >= cStart) && (p < cEnd)) {
5690             /* Old cells add new cells and interior faces and vertex */
5691             for (r = 0; r < 4; ++r) {
5692               newp = cStartNew + (p - cStart)*4 + r;
5693               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5694             }
5695             for (r = 0; r < 4; ++r) {
5696               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
5697               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5698             }
5699             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
5700             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5701           }
5702           break;
5703         case 3:
5704           /* Hybrid simplicial 2D */
5705           if ((p >= vStart) && (p < vEnd)) {
5706             /* Old vertices stay the same */
5707             newp = vStartNew + (p - vStart);
5708             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5709           } else if ((p >= fStart) && (p < fMax)) {
5710             /* Old interior faces add new faces and vertex */
5711             newp = vStartNew + (vEnd - vStart) + (p - fStart);
5712             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5713             for (r = 0; r < 2; ++r) {
5714               newp = fStartNew + (p - fStart)*2 + r;
5715               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5716             }
5717           } else if ((p >= fMax) && (p < fEnd)) {
5718             /* Old hybrid faces stay the same */
5719             newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
5720             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5721           } else if ((p >= cStart) && (p < cMax)) {
5722             /* Old interior cells add new cells and interior faces */
5723             for (r = 0; r < 4; ++r) {
5724               newp = cStartNew + (p - cStart)*4 + r;
5725               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5726             }
5727             for (r = 0; r < 3; ++r) {
5728               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
5729               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5730             }
5731           } else if ((p >= cMax) && (p < cEnd)) {
5732             /* Old hybrid cells add new cells and hybrid face */
5733             for (r = 0; r < 2; ++r) {
5734               newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
5735               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5736             }
5737             newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
5738             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5739           }
5740           break;
5741         case 5:
5742           /* Simplicial 3D */
5743           if ((p >= vStart) && (p < vEnd)) {
5744             /* Old vertices stay the same */
5745             newp = vStartNew + (p - vStart);
5746             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5747           } else if ((p >= eStart) && (p < eEnd)) {
5748             /* Old edges add new edges and vertex */
5749             for (r = 0; r < 2; ++r) {
5750               newp = eStartNew + (p - eStart)*2 + r;
5751               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5752             }
5753             newp = vStartNew + (vEnd - vStart) + (p - eStart);
5754             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5755           } else if ((p >= fStart) && (p < fEnd)) {
5756             /* Old faces add new faces and edges */
5757             for (r = 0; r < 4; ++r) {
5758               newp = fStartNew + (p - fStart)*4 + r;
5759               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5760             }
5761             for (r = 0; r < 3; ++r) {
5762               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
5763               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5764             }
5765           } else if ((p >= cStart) && (p < cEnd)) {
5766             /* Old cells add new cells and interior faces and edges */
5767             for (r = 0; r < 8; ++r) {
5768               newp = cStartNew + (p - cStart)*8 + r;
5769               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5770             }
5771             for (r = 0; r < 8; ++r) {
5772               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*8 + r;
5773               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5774             }
5775             for (r = 0; r < 1; ++r) {
5776               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*1 + r;
5777               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5778             }
5779           }
5780           break;
5781         case 7:
5782           /* Hybrid Simplicial 3D */
5783           if ((p >= vStart) && (p < vEnd)) {
5784             /* Interior vertices stay the same */
5785             newp = vStartNew + (p - vStart);
5786             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5787           } else if ((p >= eStart) && (p < eMax)) {
5788             /* Interior edges add new edges and vertex */
5789             for (r = 0; r < 2; ++r) {
5790               newp = eStartNew + (p - eStart)*2 + r;
5791               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5792             }
5793             newp = vStartNew + (vEnd - vStart) + (p - eStart);
5794             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5795           } else if ((p >= eMax) && (p < eEnd)) {
5796             /* Hybrid edges stay the same */
5797             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - eMax);
5798             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5799           } else if ((p >= fStart) && (p < fMax)) {
5800             /* Interior faces add new faces and edges */
5801             for (r = 0; r < 4; ++r) {
5802               newp = fStartNew + (p - fStart)*4 + r;
5803               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5804             }
5805             for (r = 0; r < 3; ++r) {
5806               newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
5807               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5808             }
5809           } else if ((p >= fMax) && (p < fEnd)) {
5810             /* Hybrid faces add new faces and edges */
5811             for (r = 0; r < 2; ++r) {
5812               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (p - fMax)*2 + r;
5813               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5814             }
5815             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - fMax);
5816             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5817           } else if ((p >= cStart) && (p < cMax)) {
5818             /* Interior cells add new cells, faces, and edges */
5819             for (r = 0; r < 8; ++r) {
5820               newp = cStartNew + (p - cStart)*8 + r;
5821               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5822             }
5823             for (r = 0; r < 8; ++r) {
5824               newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*8 + r;
5825               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5826             }
5827             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart);
5828             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5829           } else if ((p >= cMax) && (p < cEnd)) {
5830             /* Hybrid cells add new cells and faces */
5831             for (r = 0; r < 4; ++r) {
5832               newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
5833               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5834             }
5835             for (r = 0; r < 3; ++r) {
5836               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
5837               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5838             }
5839           }
5840           break;
5841         case 6:
5842           /* Hex 3D */
5843           if ((p >= vStart) && (p < vEnd)) {
5844             /* Old vertices stay the same */
5845             newp = vStartNew + (p - vStart);
5846             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5847           } else if ((p >= eStart) && (p < eEnd)) {
5848             /* Old edges add new edges and vertex */
5849             for (r = 0; r < 2; ++r) {
5850               newp = eStartNew + (p - eStart)*2 + r;
5851               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5852             }
5853             newp = vStartNew + (vEnd - vStart) + (p - eStart);
5854             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5855           } else if ((p >= fStart) && (p < fEnd)) {
5856             /* Old faces add new faces, edges, and vertex */
5857             for (r = 0; r < 4; ++r) {
5858               newp = fStartNew + (p - fStart)*4 + r;
5859               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5860             }
5861             for (r = 0; r < 4; ++r) {
5862               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*4 + r;
5863               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5864             }
5865             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (p - fStart);
5866             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5867           } else if ((p >= cStart) && (p < cEnd)) {
5868             /* Old cells add new cells, faces, edges, and vertex */
5869             for (r = 0; r < 8; ++r) {
5870               newp = cStartNew + (p - cStart)*8 + r;
5871               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5872             }
5873             for (r = 0; r < 12; ++r) {
5874               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*12 + r;
5875               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5876             }
5877             for (r = 0; r < 6; ++r) {
5878               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (p - cStart)*6 + r;
5879               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5880             }
5881             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (p - cStart);
5882             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5883           }
5884           break;
5885         case 8:
5886           /* Hybrid Hex 3D */
5887           if ((p >= vStart) && (p < vEnd)) {
5888             /* Interior vertices stay the same */
5889             newp = vStartNew + (p - vStart);
5890             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5891           } else if ((p >= eStart) && (p < eMax)) {
5892             /* Interior edges add new edges and vertex */
5893             for (r = 0; r < 2; ++r) {
5894               newp = eStartNew + (p - eStart)*2 + r;
5895               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5896             }
5897             newp = vStartNew + (vEnd - vStart) + (p - eStart);
5898             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5899           } else if ((p >= eMax) && (p < eEnd)) {
5900             /* Hybrid edges stay the same */
5901             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - eMax);
5902             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5903           } else if ((p >= fStart) && (p < fMax)) {
5904             /* Interior faces add new faces, edges, and vertex */
5905             for (r = 0; r < 4; ++r) {
5906               newp = fStartNew + (p - fStart)*4 + r;
5907               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5908             }
5909             for (r = 0; r < 4; ++r) {
5910               newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*4 + r;
5911               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5912             }
5913             newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (p - fStart);
5914             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5915           } else if ((p >= fMax) && (p < fEnd)) {
5916             /* Hybrid faces add new faces and edges */
5917             for (r = 0; r < 2; ++r) {
5918               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (p - fMax)*2 + r;
5919               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5920             }
5921             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - fMax);
5922             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5923           } else if ((p >= cStart) && (p < cMax)) {
5924             /* Interior cells add new cells, faces, edges, and vertex */
5925             for (r = 0; r < 8; ++r) {
5926               newp = cStartNew + (p - cStart)*8 + r;
5927               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5928             }
5929             for (r = 0; r < 12; ++r) {
5930               newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*12 + r;
5931               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5932             }
5933             for (r = 0; r < 6; ++r) {
5934               newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (p - cStart)*6 + r;
5935               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5936             }
5937             newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (p - cStart);
5938             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5939           } else if ((p >= cMax) && (p < cEnd)) {
5940             /* Hybrid cells add new cells, faces, and edges */
5941             for (r = 0; r < 4; ++r) {
5942               newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
5943               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5944             }
5945             for (r = 0; r < 4; ++r) {
5946               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (p - cMax)*4 + r;
5947               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5948             }
5949             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (fEnd - fMax) + (p - cMax);
5950             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
5951           }
5952           break;
5953         default:
5954           SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5955         }
5956       }
5957       ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
5958       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
5959     }
5960     ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
5961     ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
5962     if (0) {
5963       ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr);
5964       ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
5965       ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
5966     }
5967   }
5968   PetscFunctionReturn(0);
5969 }
5970 
5971 #undef __FUNCT__
5972 #define __FUNCT__ "DMPlexRefineUniform_Internal"
5973 /* This will only work for interpolated meshes */
5974 PetscErrorCode DMPlexRefineUniform_Internal(DM dm, CellRefiner cellRefiner, DM *dmRefined)
5975 {
5976   DM             rdm;
5977   PetscInt      *depthSize;
5978   PetscInt       dim, depth = 0, d, pStart = 0, pEnd = 0;
5979   PetscErrorCode ierr;
5980 
5981   PetscFunctionBegin;
5982   ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr);
5983   ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr);
5984   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
5985   ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr);
5986   /* Calculate number of new points of each depth */
5987   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
5988   ierr = PetscMalloc1((depth+1), &depthSize);CHKERRQ(ierr);
5989   ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr);
5990   ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr);
5991   /* Step 1: Set chart */
5992   for (d = 0; d <= depth; ++d) pEnd += depthSize[d];
5993   ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr);
5994   /* Step 2: Set cone/support sizes */
5995   ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
5996   /* Step 3: Setup refined DM */
5997   ierr = DMSetUp(rdm);CHKERRQ(ierr);
5998   /* Step 4: Set cones and supports */
5999   ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
6000   /* Step 5: Stratify */
6001   ierr = DMPlexStratify(rdm);CHKERRQ(ierr);
6002   /* Step 6: Set coordinates for vertices */
6003   ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
6004   /* Step 7: Create pointSF */
6005   ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
6006   /* Step 8: Create labels */
6007   ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
6008   ierr = PetscFree(depthSize);CHKERRQ(ierr);
6009 
6010   *dmRefined = rdm;
6011   PetscFunctionReturn(0);
6012 }
6013 
6014 #undef __FUNCT__
6015 #define __FUNCT__ "DMPlexSetRefinementUniform"
6016 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
6017 {
6018   DM_Plex *mesh = (DM_Plex*) dm->data;
6019 
6020   PetscFunctionBegin;
6021   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6022   mesh->refinementUniform = refinementUniform;
6023   PetscFunctionReturn(0);
6024 }
6025 
6026 #undef __FUNCT__
6027 #define __FUNCT__ "DMPlexGetRefinementUniform"
6028 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
6029 {
6030   DM_Plex *mesh = (DM_Plex*) dm->data;
6031 
6032   PetscFunctionBegin;
6033   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6034   PetscValidPointer(refinementUniform,  2);
6035   *refinementUniform = mesh->refinementUniform;
6036   PetscFunctionReturn(0);
6037 }
6038 
6039 #undef __FUNCT__
6040 #define __FUNCT__ "DMPlexSetRefinementLimit"
6041 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
6042 {
6043   DM_Plex *mesh = (DM_Plex*) dm->data;
6044 
6045   PetscFunctionBegin;
6046   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6047   mesh->refinementLimit = refinementLimit;
6048   PetscFunctionReturn(0);
6049 }
6050 
6051 #undef __FUNCT__
6052 #define __FUNCT__ "DMPlexGetRefinementLimit"
6053 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
6054 {
6055   DM_Plex *mesh = (DM_Plex*) dm->data;
6056 
6057   PetscFunctionBegin;
6058   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6059   PetscValidPointer(refinementLimit,  2);
6060   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
6061   *refinementLimit = mesh->refinementLimit;
6062   PetscFunctionReturn(0);
6063 }
6064 
6065 #undef __FUNCT__
6066 #define __FUNCT__ "DMPlexGetCellRefiner_Internal"
6067 PetscErrorCode DMPlexGetCellRefiner_Internal(DM dm, CellRefiner *cellRefiner)
6068 {
6069   PetscInt       dim, cStart, cEnd, coneSize, cMax;
6070   PetscErrorCode ierr;
6071 
6072   PetscFunctionBegin;
6073   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
6074   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
6075   if (cEnd <= cStart) {*cellRefiner = 0; PetscFunctionReturn(0);}
6076   ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr);
6077   ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr);
6078   switch (dim) {
6079   case 2:
6080     switch (coneSize) {
6081     case 3:
6082       if (cMax >= 0) *cellRefiner = 3; /* Hybrid */
6083       else *cellRefiner = 1; /* Triangular */
6084       break;
6085     case 4:
6086       if (cMax >= 0) *cellRefiner = 4; /* Hybrid */
6087       else *cellRefiner = 2; /* Quadrilateral */
6088       break;
6089     default:
6090       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
6091     }
6092     break;
6093   case 3:
6094     switch (coneSize) {
6095     case 4:
6096       if (cMax >= 0) *cellRefiner = 7; /* Hybrid */
6097       else *cellRefiner = 5; /* Tetrahedral */
6098       break;
6099     case 6:
6100       if (cMax >= 0) *cellRefiner = 8; /* Hybrid */
6101       else *cellRefiner = 6; /* hexahedral */
6102       break;
6103     default:
6104       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
6105     }
6106     break;
6107   default:
6108     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim);
6109   }
6110   PetscFunctionReturn(0);
6111 }
6112