Actual source code: plexrefine.c

petsc-dev 2014-02-02
Report Typos and Errors
  1: #include <petsc-private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
  2: #include <petscsf.h>

  6: PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart)
  7: {
  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:   return(0);
 14: }

 18: PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd)
 19: {
 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:   return(0);
 26: }

 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;

 36:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
 37:   DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
 38:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
 39:   DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
 40:   DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
 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 + cEnd - cStart + fEnd - fStart; /* 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:   return(0);
114: }

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: }

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: }

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: }


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: }

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: }

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;

165:   DMPlexGetDepth(dm, &depth);
166:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
167:   DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
168:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
169:   DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
170:   DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
171:   if (refiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
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;

181:         DMPlexSetConeSize(rdm, newp, 3);
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;

190:         DMPlexSetConeSize(rdm, newp, 2);
191:         DMPlexGetSupportSize(dm, f, &size);
192:         DMPlexSetSupportSize(rdm, newp, size);
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;

200:         DMPlexSetConeSize(rdm, newp, 2);
201:         DMPlexSetSupportSize(rdm, newp, 2);
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;

209:       DMPlexGetSupportSize(dm, v, &size);
210:       DMPlexSetSupportSize(rdm, newp, size);
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;

217:       DMPlexGetSupportSize(dm, f, &size);
218:       DMPlexSetSupportSize(rdm, newp, 2 + size*2);
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 = (c - cStart)*4 + r;

228:         DMPlexSetConeSize(rdm, newp, 4);
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;

237:         DMPlexSetConeSize(rdm, newp, 2);
238:         DMPlexGetSupportSize(dm, f, &size);
239:         DMPlexSetSupportSize(rdm, newp, size);
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;

247:         DMPlexSetConeSize(rdm, newp, 2);
248:         DMPlexSetSupportSize(rdm, newp, 2);
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;

256:       DMPlexGetSupportSize(dm, v, &size);
257:       DMPlexSetSupportSize(rdm, newp, size);
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;

264:       DMPlexGetSupportSize(dm, f, &size);
265:       DMPlexSetSupportSize(rdm, newp, 2 + size);
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);

271:       DMPlexSetSupportSize(rdm, newp, 4);
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:     DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);
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;

286:         DMPlexSetConeSize(rdm, newp, 3);
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;

294:         DMPlexSetConeSize(rdm, newp, 4);
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;

303:         DMPlexSetConeSize(rdm, newp, 2);
304:         DMPlexGetSupportSize(dm, f, &size);
305:         DMPlexSetSupportSize(rdm, newp, size);
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;

313:         DMPlexSetConeSize(rdm, newp, 2);
314:         DMPlexSetSupportSize(rdm, newp, 2);
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;

322:       DMPlexSetConeSize(rdm, newp, 2);
323:       DMPlexGetSupportSize(dm, f, &size);
324:       DMPlexSetSupportSize(rdm, newp, size);
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);

330:       DMPlexSetConeSize(rdm, newp, 2);
331:       DMPlexSetSupportSize(rdm, newp, 2);
332:     }
333:     /* Old vertices have identical supports */
334:     for (v = vStart; v < vEnd; ++v) {
335:       const PetscInt newp = vStartNew + (v - vStart);
336:       PetscInt       size;

338:       DMPlexGetSupportSize(dm, v, &size);
339:       DMPlexSetSupportSize(rdm, newp, size);
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;

347:       DMPlexGetSupportSize(dm, f, &size);
348:       DMPlexGetSupport(dm, f, &support);
349:       for (s = 0; s < size; ++s) {
350:         if (support[s] >= cMax) newSize += 1;
351:         else newSize += 2;
352:       }
353:       DMPlexSetSupportSize(rdm, newp, newSize);
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;

363:         DMPlexSetConeSize(rdm, newp, 4);
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;

372:         DMPlexSetConeSize(rdm, newp, 3);
373:         DMPlexGetSupportSize(dm, f, &size);
374:         DMPlexSetSupportSize(rdm, newp, size);
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;

382:         DMPlexSetConeSize(rdm, newp, 3);
383:         DMPlexSetSupportSize(rdm, newp, 2);
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;

392:         DMPlexSetConeSize(rdm, newp, 2);
393:         DMPlexGetSupportSize(dm, e, &size);
394:         DMPlexSetSupportSize(rdm, newp, size);
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;

404:         DMPlexSetConeSize(rdm, newp, 2);
405:         DMPlexGetSupportSize(dm, f, &supportSize);
406:         DMPlexGetSupport(dm, f, &support);
407:         for (s = 0; s < supportSize; ++s) {
408:           DMPlexGetConeSize(dm, support[s], &coneSize);
409:           DMPlexGetCone(dm, support[s], &cone);
410:           DMPlexGetConeOrientation(dm, support[s], &ornt);
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:         DMPlexSetSupportSize(rdm, newp, 2+intFaces);
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);

427:       DMPlexSetConeSize(rdm, newp, 2);
428:       DMPlexSetSupportSize(rdm, newp, 4);
429:     }
430:     /* Old vertices have identical supports */
431:     for (v = vStart; v < vEnd; ++v) {
432:       const PetscInt newp = vStartNew + (v - vStart);
433:       PetscInt       size;

435:       DMPlexGetSupportSize(dm, v, &size);
436:       DMPlexSetSupportSize(rdm, newp, size);
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;

443:       DMPlexGetSupportSize(dm, e, &size);
444:       DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
445:       for (s = 0; s < starSize*2; s += 2) {
446:         const PetscInt *cone, *ornt;
447:         PetscInt        e01, e23;

449:         if ((star[s] >= cStart) && (star[s] < cEnd)) {
450:           /* Check edge 0-1 */
451:           DMPlexGetCone(dm, star[s], &cone);
452:           DMPlexGetConeOrientation(dm, star[s], &ornt);
453:           DMPlexGetCone(dm, cone[0], &cone);
454:           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
455:           /* Check edge 2-3 */
456:           DMPlexGetCone(dm, star[s], &cone);
457:           DMPlexGetConeOrientation(dm, star[s], &ornt);
458:           DMPlexGetCone(dm, cone[2], &cone);
459:           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
460:           if ((e01 == e) || (e23 == e)) ++cellSize;
461:         }
462:       }
463:       DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
464:       DMPlexSetSupportSize(rdm, newp, 2 + size*2 + cellSize);
465:     }
466:     break;
467:   case 7:
468:     /* Hybrid Simplicial 3D */
469:     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);
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;

476:         DMPlexSetConeSize(rdm, newp, 4);
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;

484:         DMPlexSetConeSize(rdm, newp, 5);
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;

493:         DMPlexSetConeSize(rdm, newp, 3);
494:         DMPlexGetSupportSize(dm, f, &size);
495:         DMPlexSetSupportSize(rdm, newp, size);
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;

503:         DMPlexSetConeSize(rdm, newp, 3);
504:         DMPlexSetSupportSize(rdm, newp, 2);
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;

513:         DMPlexSetConeSize(rdm, newp, 4);
514:         DMPlexGetSupportSize(dm, f, &size);
515:         DMPlexSetSupportSize(rdm, newp, size);
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;

523:         DMPlexSetConeSize(rdm, newp, 4);
524:         DMPlexSetSupportSize(rdm, newp, 2);
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;

533:         DMPlexSetConeSize(rdm, newp, 2);
534:         DMPlexGetSupportSize(dm, e, &size);
535:         DMPlexSetSupportSize(rdm, newp, size);
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;

545:         DMPlexSetConeSize(rdm, newp, 2);
546:         DMPlexGetSupportSize(dm, f, &supportSize);
547:         DMPlexGetSupport(dm, f, &support);
548:         for (s = 0; s < supportSize; ++s) {
549:           DMPlexGetConeSize(dm, support[s], &coneSize);
550:           DMPlexGetCone(dm, support[s], &cone);
551:           DMPlexGetConeOrientation(dm, support[s], &ornt);
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:         DMPlexSetSupportSize(rdm, newp, 2+intFaces);
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);

572:       DMPlexSetConeSize(rdm, newp, 2);
573:       DMPlexSetSupportSize(rdm, newp, 4);
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;

580:       DMPlexSetConeSize(rdm, newp, 2);
581:       DMPlexGetSupportSize(dm, e, &size);
582:       DMPlexSetSupportSize(rdm, newp, size);
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;

589:       DMPlexSetConeSize(rdm, newp, 2);
590:       DMPlexGetSupportSize(dm, f, &size);
591:       DMPlexSetSupportSize(rdm, newp, 2+2*size);
592:     }
593:     /* Interior vertices have identical supports */
594:     for (v = vStart; v < vEnd; ++v) {
595:       const PetscInt newp = vStartNew + (v - vStart);
596:       PetscInt       size;

598:       DMPlexGetSupportSize(dm, v, &size);
599:       DMPlexSetSupportSize(rdm, newp, size);
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;

607:       DMPlexGetSupportSize(dm, e, &size);
608:       DMPlexGetSupport(dm, e, &support);
609:       for (s = 0; s < size; ++s) {
610:         if (support[s] < fMax) faceSize += 2;
611:         else                   faceSize += 1;
612:       }
613:       DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
614:       for (s = 0; s < starSize*2; s += 2) {
615:         const PetscInt *cone, *ornt;
616:         PetscInt        e01, e23;

618:         if ((star[s] >= cStart) && (star[s] < cMax)) {
619:           /* Check edge 0-1 */
620:           DMPlexGetCone(dm, star[s], &cone);
621:           DMPlexGetConeOrientation(dm, star[s], &ornt);
622:           DMPlexGetCone(dm, cone[0], &cone);
623:           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
624:           /* Check edge 2-3 */
625:           DMPlexGetCone(dm, star[s], &cone);
626:           DMPlexGetConeOrientation(dm, star[s], &ornt);
627:           DMPlexGetCone(dm, cone[2], &cone);
628:           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
629:           if ((e01 == e) || (e23 == e)) ++cellSize;
630:         }
631:       }
632:       DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
633:       DMPlexSetSupportSize(rdm, newp, 2 + faceSize + cellSize);
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;

643:         DMPlexSetConeSize(rdm, newp, 6);
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;

652:         DMPlexSetConeSize(rdm, newp, 4);
653:         DMPlexGetSupportSize(dm, f, &size);
654:         DMPlexSetSupportSize(rdm, newp, size);
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;

662:         DMPlexSetConeSize(rdm, newp, 4);
663:         DMPlexSetSupportSize(rdm, newp, 2);
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;

672:         DMPlexSetConeSize(rdm, newp, 2);
673:         DMPlexGetSupportSize(dm, e, &size);
674:         DMPlexSetSupportSize(rdm, newp, size);
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;

683:         DMPlexSetConeSize(rdm, newp, 2);
684:         DMPlexGetSupportSize(dm, f, &size);
685:         DMPlexSetSupportSize(rdm, newp, 2+size);
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;

693:         DMPlexSetConeSize(rdm, newp, 2);
694:         DMPlexSetSupportSize(rdm, newp, 4);
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;

702:       DMPlexGetSupportSize(dm, v, &size);
703:       DMPlexSetSupportSize(rdm, newp, size);
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;

710:       DMPlexGetSupportSize(dm, e, &size);
711:       DMPlexSetSupportSize(rdm, newp, 2 + size);
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;

718:       DMPlexGetSupportSize(dm, f, &size);
719:       DMPlexSetSupportSize(rdm, newp, 4 + size);
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);

725:       DMPlexSetSupportSize(rdm, newp, 6);
726:     }
727:     break;
728:   case 8:
729:     /* Hybrid Hex 3D */
730:     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);
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;

737:         DMPlexSetConeSize(rdm, newp, 6);
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;

745:         DMPlexSetConeSize(rdm, newp, 6);
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;

754:         DMPlexSetConeSize(rdm, newp, 4);
755:         DMPlexGetSupportSize(dm, f, &size);
756:         DMPlexSetSupportSize(rdm, newp, size);
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;

764:         DMPlexSetConeSize(rdm, newp, 4);
765:         DMPlexSetSupportSize(rdm, newp, 2);
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;

774:         DMPlexSetConeSize(rdm, newp, 4);
775:         DMPlexGetSupportSize(dm, f, &size);
776:         DMPlexSetSupportSize(rdm, newp, size);
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;

784:         DMPlexSetConeSize(rdm, newp, 4);
785:         DMPlexSetSupportSize(rdm, newp, 2);
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;

794:         DMPlexSetConeSize(rdm, newp, 2);
795:         DMPlexGetSupportSize(dm, e, &size);
796:         DMPlexSetSupportSize(rdm, newp, size);
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;

805:         DMPlexSetConeSize(rdm, newp, 2);
806:         DMPlexGetSupportSize(dm, f, &size);
807:         DMPlexSetSupportSize(rdm, newp, 2+size);
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;

815:         DMPlexSetConeSize(rdm, newp, 2);
816:         DMPlexSetSupportSize(rdm, newp, 4);
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;

824:       DMPlexSetConeSize(rdm, newp, 2);
825:       DMPlexGetSupportSize(dm, e, &size);
826:       DMPlexSetSupportSize(rdm, newp, size);
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;

833:       DMPlexSetConeSize(rdm, newp, 2);
834:       DMPlexGetSupportSize(dm, f, &size);
835:       DMPlexSetSupportSize(rdm, newp, 2+size);
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);

841:       DMPlexSetConeSize(rdm, newp, 2);
842:       DMPlexSetSupportSize(rdm, newp, 4);
843:     }
844:     /* Interior vertices have identical supports */
845:     for (v = vStart; v < vEnd; ++v) {
846:       const PetscInt newp = vStartNew + (v - vStart);
847:       PetscInt       size;

849:       DMPlexGetSupportSize(dm, v, &size);
850:       DMPlexSetSupportSize(rdm, newp, size);
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;

857:       DMPlexGetSupportSize(dm, e, &size);
858:       DMPlexSetSupportSize(rdm, newp, 2 + size);
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;

865:       DMPlexGetSupportSize(dm, f, &size);
866:       DMPlexSetSupportSize(rdm, newp, 4 + size);
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);

872:       DMPlexSetSupportSize(rdm, newp, 6);
873:     }
874:     break;
875:   default:
876:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
877:   }
878:   return(0);
879: }

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;

892:   DMPlexGetDepth(dm, &depth);
893:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
894:   DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
895:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
896:   DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
897:   DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
898:   if (refiner) {
899:     GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);
900:     GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);
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];

927:       DMPlexGetCone(dm, c, &cone);
928:       DMPlexGetConeOrientation(dm, c, &ornt);
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:       DMPlexSetCone(rdm, newp+0, coneNew);
937:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
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:       DMPlexSetCone(rdm, newp+1, coneNew);
952:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
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:       DMPlexSetCone(rdm, newp+2, coneNew);
967:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
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:       DMPlexSetCone(rdm, newp+3, coneNew);
982:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
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:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
992:     PetscMalloc1((2 + maxSupportSize*2), &supportRef);
993:     for (f = fStart; f < fEnd; ++f) {
994:       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);

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;

1001:         DMPlexGetCone(dm, f, &cone);
1002:         coneNew[0]       = vStartNew + (cone[0] - vStart);
1003:         coneNew[1]       = vStartNew + (cone[1] - vStart);
1004:         coneNew[(r+1)%2] = newv;
1005:         DMPlexSetCone(rdm, newp, coneNew);
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:         DMPlexGetSupportSize(dm, f, &supportSize);
1013:         DMPlexGetSupport(dm, f, &support);
1014:         for (s = 0; s < supportSize; ++s) {
1015:           DMPlexGetConeSize(dm, support[s], &coneSize);
1016:           DMPlexGetCone(dm, support[s], &cone);
1017:           DMPlexGetConeOrientation(dm, support[s], &ornt);
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:         DMPlexSetSupport(rdm, newp, supportRef);
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;

1036:       DMPlexGetCone(dm, c, &cone);
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];

1042:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
1043:         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
1044:         DMPlexSetCone(rdm, newp, coneNew);
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:         DMPlexSetSupport(rdm, newp, supportNew);
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;

1068:       DMPlexGetSupportSize(dm, v, &size);
1069:       DMPlexGetSupport(dm, v, &support);
1070:       for (s = 0; s < size; ++s) {
1071:         PetscInt r = 0;

1073:         DMPlexGetCone(dm, support[s], &cone);
1074:         if (cone[1] == v) r = 1;
1075:         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1076:       }
1077:       DMPlexSetSupport(rdm, newp, supportRef);
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;

1091:       DMPlexGetSupportSize(dm, f, &size);
1092:       DMPlexGetSupport(dm, f, &support);
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;

1098:         DMPlexGetCone(dm, support[s], &cone);
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:       DMPlexSetSupport(rdm, newp, supportRef);
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:     PetscFree(supportRef);
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];

1133:       DMPlexGetCone(dm, c, &cone);
1134:       DMPlexGetConeOrientation(dm, c, &ornt);
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:       DMPlexSetCone(rdm, newp+0, coneNew);
1145:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
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:       DMPlexSetCone(rdm, newp+1, coneNew);
1162:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
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:       DMPlexSetCone(rdm, newp+2, coneNew);
1179:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
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:       DMPlexSetCone(rdm, newp+3, coneNew);
1196:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
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:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
1206:     PetscMalloc1((2 + maxSupportSize*2), &supportRef);
1207:     for (f = fStart; f < fEnd; ++f) {
1208:       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);

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;

1215:         DMPlexGetCone(dm, f, &cone);
1216:         coneNew[0]       = vStartNew + (cone[0] - vStart);
1217:         coneNew[1]       = vStartNew + (cone[1] - vStart);
1218:         coneNew[(r+1)%2] = newv;
1219:         DMPlexSetCone(rdm, newp, coneNew);
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:         DMPlexGetSupportSize(dm, f, &supportSize);
1227:         DMPlexGetSupport(dm, f, &support);
1228:         for (s = 0; s < supportSize; ++s) {
1229:           DMPlexGetConeSize(dm, support[s], &coneSize);
1230:           DMPlexGetCone(dm, support[s], &cone);
1231:           DMPlexGetConeOrientation(dm, support[s], &ornt);
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:         DMPlexSetSupport(rdm, newp, supportRef);
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];

1251:       DMPlexGetCone(dm, c, &cone);
1252:       for (r = 0; r < 4; ++r) {
1253:         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;

1255:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
1256:         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
1257:         DMPlexSetCone(rdm, newp, coneNew);
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:         DMPlexSetSupport(rdm, newp, supportNew);
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;

1281:       DMPlexGetSupportSize(dm, v, &size);
1282:       DMPlexGetSupport(dm, v, &support);
1283:       for (s = 0; s < size; ++s) {
1284:         PetscInt r = 0;

1286:         DMPlexGetCone(dm, support[s], &cone);
1287:         if (cone[1] == v) r = 1;
1288:         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1289:       }
1290:       DMPlexSetSupport(rdm, newp, supportRef);
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;

1304:       DMPlexGetSupportSize(dm, f, &size);
1305:       DMPlexGetSupport(dm, f, &support);
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;

1311:         DMPlexGetCone(dm, support[s], &cone);
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:       DMPlexSetSupport(rdm, newp, supportRef);
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];

1330:       for (r = 0; r < 4; ++r) {
1331:         supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
1332:       }
1333:       DMPlexSetSupport(rdm, newp, supportNew);
1334:     }
1335:     PetscFree(supportRef);
1336:     break;
1337:   case 3:
1338:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
1339:     cMax = PetscMin(cEnd, cMax);
1340:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
1341:     fMax = PetscMin(fEnd, fMax);
1342:     /* Interior cells have 3 faces */
1343:     for (c = cStart; c < cMax; ++c) {
1344:       const PetscInt  newp = cStartNew + (c - cStart)*4;
1345:       const PetscInt *cone, *ornt;
1346:       PetscInt        coneNew[3], orntNew[3];

1348:       DMPlexGetCone(dm, c, &cone);
1349:       DMPlexGetConeOrientation(dm, c, &ornt);
1350:       /* A triangle */
1351:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1352:       orntNew[0] = ornt[0];
1353:       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
1354:       orntNew[1] = -2;
1355:       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1356:       orntNew[2] = ornt[2];
1357:       DMPlexSetCone(rdm, newp+0, coneNew);
1358:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1359: #if 1
1360:       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);
1361:       for (p = 0; p < 3; ++p) {
1362:         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);
1363:       }
1364: #endif
1365:       /* B triangle */
1366:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1367:       orntNew[0] = ornt[0];
1368:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1369:       orntNew[1] = ornt[1];
1370:       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
1371:       orntNew[2] = -2;
1372:       DMPlexSetCone(rdm, newp+1, coneNew);
1373:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1374: #if 1
1375:       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);
1376:       for (p = 0; p < 3; ++p) {
1377:         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);
1378:       }
1379: #endif
1380:       /* C triangle */
1381:       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
1382:       orntNew[0] = -2;
1383:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1384:       orntNew[1] = ornt[1];
1385:       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1386:       orntNew[2] = ornt[2];
1387:       DMPlexSetCone(rdm, newp+2, coneNew);
1388:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
1389: #if 1
1390:       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);
1391:       for (p = 0; p < 3; ++p) {
1392:         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);
1393:       }
1394: #endif
1395:       /* D triangle */
1396:       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
1397:       orntNew[0] = 0;
1398:       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
1399:       orntNew[1] = 0;
1400:       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
1401:       orntNew[2] = 0;
1402:       DMPlexSetCone(rdm, newp+3, coneNew);
1403:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
1404: #if 1
1405:       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);
1406:       for (p = 0; p < 3; ++p) {
1407:         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);
1408:       }
1409: #endif
1410:     }
1411:     /*
1412:      2----3----3
1413:      |         |
1414:      |    B    |
1415:      |         |
1416:      0----4--- 1
1417:      |         |
1418:      |    A    |
1419:      |         |
1420:      0----2----1
1421:      */
1422:     /* Hybrid cells have 4 faces */
1423:     for (c = cMax; c < cEnd; ++c) {
1424:       const PetscInt  newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
1425:       const PetscInt *cone, *ornt;
1426:       PetscInt        coneNew[4], orntNew[4];

1428:       DMPlexGetCone(dm, c, &cone);
1429:       DMPlexGetConeOrientation(dm, c, &ornt);
1430:       /* A quad */
1431:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1432:       orntNew[0] = ornt[0];
1433:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1434:       orntNew[1] = ornt[1];
1435:       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax);
1436:       orntNew[2] = 0;
1437:       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
1438:       orntNew[3] = 0;
1439:       DMPlexSetCone(rdm, newp+0, coneNew);
1440:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1441: #if 1
1442:       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);
1443:       for (p = 0; p < 4; ++p) {
1444:         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);
1445:       }
1446: #endif
1447:       /* B quad */
1448:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1449:       orntNew[0] = ornt[0];
1450:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1451:       orntNew[1] = ornt[1];
1452:       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
1453:       orntNew[2] = 0;
1454:       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax);
1455:       orntNew[3] = 0;
1456:       DMPlexSetCone(rdm, newp+1, coneNew);
1457:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1458: #if 1
1459:       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);
1460:       for (p = 0; p < 4; ++p) {
1461:         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);
1462:       }
1463: #endif
1464:     }
1465:     /* Interior split faces have 2 vertices and the same cells as the parent */
1466:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
1467:     PetscMalloc1((2 + maxSupportSize*2), &supportRef);
1468:     for (f = fStart; f < fMax; ++f) {
1469:       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);

1471:       for (r = 0; r < 2; ++r) {
1472:         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
1473:         const PetscInt *cone, *ornt, *support;
1474:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

1476:         DMPlexGetCone(dm, f, &cone);
1477:         coneNew[0]       = vStartNew + (cone[0] - vStart);
1478:         coneNew[1]       = vStartNew + (cone[1] - vStart);
1479:         coneNew[(r+1)%2] = newv;
1480:         DMPlexSetCone(rdm, newp, coneNew);
1481: #if 1
1482:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1483:         for (p = 0; p < 2; ++p) {
1484:           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);
1485:         }
1486: #endif
1487:         DMPlexGetSupportSize(dm, f, &supportSize);
1488:         DMPlexGetSupport(dm, f, &support);
1489:         for (s = 0; s < supportSize; ++s) {
1490:           if (support[s] >= cMax) {
1491:             supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
1492:           } else {
1493:             DMPlexGetConeSize(dm, support[s], &coneSize);
1494:             DMPlexGetCone(dm, support[s], &cone);
1495:             DMPlexGetConeOrientation(dm, support[s], &ornt);
1496:             for (c = 0; c < coneSize; ++c) {
1497:               if (cone[c] == f) break;
1498:             }
1499:             supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
1500:           }
1501:         }
1502:         DMPlexSetSupport(rdm, newp, supportRef);
1503: #if 1
1504:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1505:         for (p = 0; p < supportSize; ++p) {
1506:           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);
1507:         }
1508: #endif
1509:       }
1510:     }
1511:     /* Interior cell faces have 2 vertices and 2 cells */
1512:     for (c = cStart; c < cMax; ++c) {
1513:       const PetscInt *cone;

1515:       DMPlexGetCone(dm, c, &cone);
1516:       for (r = 0; r < 3; ++r) {
1517:         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
1518:         PetscInt       coneNew[2];
1519:         PetscInt       supportNew[2];

1521:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
1522:         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
1523:         DMPlexSetCone(rdm, newp, coneNew);
1524: #if 1
1525:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1526:         for (p = 0; p < 2; ++p) {
1527:           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);
1528:         }
1529: #endif
1530:         supportNew[0] = (c - cStart)*4 + (r+1)%3;
1531:         supportNew[1] = (c - cStart)*4 + 3;
1532:         DMPlexSetSupport(rdm, newp, supportNew);
1533: #if 1
1534:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1535:         for (p = 0; p < 2; ++p) {
1536:           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);
1537:         }
1538: #endif
1539:       }
1540:     }
1541:     /* Interior hybrid faces have 2 vertices and the same cells */
1542:     for (f = fMax; f < fEnd; ++f) {
1543:       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
1544:       const PetscInt *cone;
1545:       const PetscInt *support;
1546:       PetscInt        coneNew[2];
1547:       PetscInt        supportNew[2];
1548:       PetscInt        size, s, r;

1550:       DMPlexGetCone(dm, f, &cone);
1551:       coneNew[0] = vStartNew + (cone[0] - vStart);
1552:       coneNew[1] = vStartNew + (cone[1] - vStart);
1553:       DMPlexSetCone(rdm, newp, coneNew);
1554: #if 1
1555:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1556:       for (p = 0; p < 2; ++p) {
1557:         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);
1558:       }
1559: #endif
1560:       DMPlexGetSupportSize(dm, f, &size);
1561:       DMPlexGetSupport(dm, f, &support);
1562:       for (s = 0; s < size; ++s) {
1563:         DMPlexGetCone(dm, support[s], &cone);
1564:         for (r = 0; r < 2; ++r) {
1565:           if (cone[r+2] == f) break;
1566:         }
1567:         supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
1568:       }
1569:       DMPlexSetSupport(rdm, newp, supportNew);
1570: #if 1
1571:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1572:       for (p = 0; p < size; ++p) {
1573:         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);
1574:       }
1575: #endif
1576:     }
1577:     /* Cell hybrid faces have 2 vertices and 2 cells */
1578:     for (c = cMax; c < cEnd; ++c) {
1579:       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
1580:       const PetscInt *cone;
1581:       PetscInt        coneNew[2];
1582:       PetscInt        supportNew[2];

1584:       DMPlexGetCone(dm, c, &cone);
1585:       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
1586:       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
1587:       DMPlexSetCone(rdm, newp, coneNew);
1588: #if 1
1589:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1590:       for (p = 0; p < 2; ++p) {
1591:         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);
1592:       }
1593: #endif
1594:       supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
1595:       supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
1596:       DMPlexSetSupport(rdm, newp, supportNew);
1597: #if 1
1598:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1599:       for (p = 0; p < 2; ++p) {
1600:         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);
1601:       }
1602: #endif
1603:     }
1604:     /* Old vertices have identical supports */
1605:     for (v = vStart; v < vEnd; ++v) {
1606:       const PetscInt  newp = vStartNew + (v - vStart);
1607:       const PetscInt *support, *cone;
1608:       PetscInt        size, s;

1610:       DMPlexGetSupportSize(dm, v, &size);
1611:       DMPlexGetSupport(dm, v, &support);
1612:       for (s = 0; s < size; ++s) {
1613:         if (support[s] >= fMax) {
1614:           supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax);
1615:         } else {
1616:           PetscInt r = 0;

1618:           DMPlexGetCone(dm, support[s], &cone);
1619:           if (cone[1] == v) r = 1;
1620:           supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1621:         }
1622:       }
1623:       DMPlexSetSupport(rdm, newp, supportRef);
1624: #if 1
1625:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1626:       for (p = 0; p < size; ++p) {
1627:         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);
1628:       }
1629: #endif
1630:     }
1631:     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
1632:     for (f = fStart; f < fMax; ++f) {
1633:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
1634:       const PetscInt *cone, *support;
1635:       PetscInt        size, newSize = 2, s;

1637:       DMPlexGetSupportSize(dm, f, &size);
1638:       DMPlexGetSupport(dm, f, &support);
1639:       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1640:       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1641:       for (s = 0; s < size; ++s) {
1642:         PetscInt r = 0;

1644:         DMPlexGetCone(dm, support[s], &cone);
1645:         if (support[s] >= cMax) {
1646:           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax);

1648:           newSize += 1;
1649:         } else {
1650:           if      (cone[1] == f) r = 1;
1651:           else if (cone[2] == f) r = 2;
1652:           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
1653:           supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r;

1655:           newSize += 2;
1656:         }
1657:       }
1658:       DMPlexSetSupport(rdm, newp, supportRef);
1659: #if 1
1660:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1661:       for (p = 0; p < newSize; ++p) {
1662:         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);
1663:       }
1664: #endif
1665:     }
1666:     PetscFree(supportRef);
1667:     break;
1668:   case 5:
1669:     /* Simplicial 3D */
1670:     /* All cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
1671:     DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
1672:     for (c = cStart; c < cEnd; ++c) {
1673:       const PetscInt  newp = cStartNew + (c - cStart)*8;
1674:       const PetscInt *cone, *ornt;
1675:       PetscInt        coneNew[4], orntNew[4];

1677:       DMPlexGetCone(dm, c, &cone);
1678:       DMPlexGetConeOrientation(dm, c, &ornt);
1679:       /* A tetrahedron: {0, a, c, d} */
1680:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
1681:       orntNew[0] = ornt[0];
1682:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
1683:       orntNew[1] = ornt[1];
1684:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
1685:       orntNew[2] = ornt[2];
1686:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
1687:       orntNew[3] = 0;
1688:       DMPlexSetCone(rdm, newp+0, coneNew);
1689:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1690: #if 1
1691:       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);
1692:       for (p = 0; p < 4; ++p) {
1693:         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);
1694:       }
1695: #endif
1696:       /* B tetrahedron: {a, 1, b, e} */
1697:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
1698:       orntNew[0] = ornt[0];
1699:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
1700:       orntNew[1] = ornt[1];
1701:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
1702:       orntNew[2] = 0;
1703:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
1704:       orntNew[3] = ornt[3];
1705:       DMPlexSetCone(rdm, newp+1, coneNew);
1706:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1707: #if 1
1708:       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);
1709:       for (p = 0; p < 4; ++p) {
1710:         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);
1711:       }
1712: #endif
1713:       /* C tetrahedron: {c, b, 2, f} */
1714:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
1715:       orntNew[0] = ornt[0];
1716:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
1717:       orntNew[1] = 0;
1718:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
1719:       orntNew[2] = ornt[2];
1720:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
1721:       orntNew[3] = ornt[3];
1722:       DMPlexSetCone(rdm, newp+2, coneNew);
1723:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
1724: #if 1
1725:       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);
1726:       for (p = 0; p < 4; ++p) {
1727:         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);
1728:       }
1729: #endif
1730:       /* D tetrahedron: {d, e, f, 3} */
1731:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
1732:       orntNew[0] = 0;
1733:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
1734:       orntNew[1] = ornt[1];
1735:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
1736:       orntNew[2] = ornt[2];
1737:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
1738:       orntNew[3] = ornt[3];
1739:       DMPlexSetCone(rdm, newp+3, coneNew);
1740:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
1741: #if 1
1742:       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);
1743:       for (p = 0; p < 4; ++p) {
1744:         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);
1745:       }
1746: #endif
1747:       /* A' tetrahedron: {d, a, c, f} */
1748:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
1749:       orntNew[0] = -3;
1750:       coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
1751:       orntNew[1] = ornt[2] < 0 ? -(GetTetSomething_Static(ornt[2], 0)+1) : GetTetSomething_Static(ornt[2], 0);
1752:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
1753:       orntNew[2] = 0;
1754:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
1755:       orntNew[3] = 2;
1756:       DMPlexSetCone(rdm, newp+4, coneNew);
1757:       DMPlexSetConeOrientation(rdm, newp+4, orntNew);
1758: #if 1
1759:       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);
1760:       for (p = 0; p < 4; ++p) {
1761:         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);
1762:       }
1763: #endif
1764:       /* B' tetrahedron: {e, b, a, f} */
1765:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
1766:       orntNew[0] = -3;
1767:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
1768:       orntNew[1] = 1;
1769:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
1770:       orntNew[2] = 0;
1771:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + 3;
1772:       orntNew[3] = ornt[3] < 0 ? -(GetTetSomething_Static(ornt[3], 0)+1) : GetTetSomething_Static(ornt[3], 0);
1773:       DMPlexSetCone(rdm, newp+5, coneNew);
1774:       DMPlexSetConeOrientation(rdm, newp+5, orntNew);
1775: #if 1
1776:       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);
1777:       for (p = 0; p < 4; ++p) {
1778:         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);
1779:       }
1780: #endif
1781:       /* C' tetrahedron: {b, f, c, a} */
1782:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
1783:       orntNew[0] = -3;
1784:       coneNew[1] = fStartNew + (cone[0] - fStart)*4 + 3;
1785:       orntNew[1] = ornt[0] < 0 ? -(GetTetSomething_Static(ornt[0], 2)+1) : GetTetSomething_Static(ornt[0], 2);
1786:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
1787:       orntNew[2] = -3;
1788:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
1789:       orntNew[3] = -2;
1790:       DMPlexSetCone(rdm, newp+6, coneNew);
1791:       DMPlexSetConeOrientation(rdm, newp+6, orntNew);
1792: #if 1
1793:       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);
1794:       for (p = 0; p < 4; ++p) {
1795:         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);
1796:       }
1797: #endif
1798:       /* D' tetrahedron: {f, e, d, a} */
1799:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
1800:       orntNew[0] = -3;
1801:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
1802:       orntNew[1] = -3;
1803:       coneNew[2] = fStartNew + (cone[1] - fStart)*4 + 3;
1804:       orntNew[2] = ornt[1] < 0 ? -(GetTetSomething_Static(ornt[1], 0)+1) : GetTetSomething_Static(ornt[1], 0);
1805:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
1806:       orntNew[3] = -3;
1807:       DMPlexSetCone(rdm, newp+7, coneNew);
1808:       DMPlexSetConeOrientation(rdm, newp+7, orntNew);
1809: #if 1
1810:       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);
1811:       for (p = 0; p < 4; ++p) {
1812:         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);
1813:       }
1814: #endif
1815:     }
1816:     /* Split faces have 3 edges and the same cells as the parent */
1817:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
1818:     PetscMalloc1((2 + maxSupportSize*2), &supportRef);
1819:     for (f = fStart; f < fEnd; ++f) {
1820:       const PetscInt  newp = fStartNew + (f - fStart)*4;
1821:       const PetscInt *cone, *ornt, *support;
1822:       PetscInt        coneNew[3], orntNew[3], coneSize, supportSize, s;

1824:       DMPlexGetCone(dm, f, &cone);
1825:       DMPlexGetConeOrientation(dm, f, &ornt);
1826:       /* A triangle */
1827:       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
1828:       orntNew[0] = ornt[0];
1829:       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
1830:       orntNew[1] = -2;
1831:       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
1832:       orntNew[2] = ornt[2];
1833:       DMPlexSetCone(rdm, newp+0, coneNew);
1834:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1835: #if 1
1836:       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);
1837:       for (p = 0; p < 3; ++p) {
1838:         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);
1839:       }
1840: #endif
1841:       /* B triangle */
1842:       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
1843:       orntNew[0] = ornt[0];
1844:       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
1845:       orntNew[1] = ornt[1];
1846:       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
1847:       orntNew[2] = -2;
1848:       DMPlexSetCone(rdm, newp+1, coneNew);
1849:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1850: #if 1
1851:       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);
1852:       for (p = 0; p < 3; ++p) {
1853:         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);
1854:       }
1855: #endif
1856:       /* C triangle */
1857:       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
1858:       orntNew[0] = -2;
1859:       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
1860:       orntNew[1] = ornt[1];
1861:       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
1862:       orntNew[2] = ornt[2];
1863:       DMPlexSetCone(rdm, newp+2, coneNew);
1864:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
1865: #if 1
1866:       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);
1867:       for (p = 0; p < 3; ++p) {
1868:         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);
1869:       }
1870: #endif
1871:       /* D triangle */
1872:       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
1873:       orntNew[0] = 0;
1874:       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
1875:       orntNew[1] = 0;
1876:       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
1877:       orntNew[2] = 0;
1878:       DMPlexSetCone(rdm, newp+3, coneNew);
1879:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
1880: #if 1
1881:       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);
1882:       for (p = 0; p < 3; ++p) {
1883:         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);
1884:       }
1885: #endif
1886:       DMPlexGetSupportSize(dm, f, &supportSize);
1887:       DMPlexGetSupport(dm, f, &support);
1888:       for (r = 0; r < 4; ++r) {
1889:         for (s = 0; s < supportSize; ++s) {
1890:           PetscInt subf;
1891:           DMPlexGetConeSize(dm, support[s], &coneSize);
1892:           DMPlexGetCone(dm, support[s], &cone);
1893:           DMPlexGetConeOrientation(dm, support[s], &ornt);
1894:           for (c = 0; c < coneSize; ++c) {
1895:             if (cone[c] == f) break;
1896:           }
1897:           subf = GetTriSubfaceInverse_Static(ornt[c], r);
1898:           supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
1899:         }
1900:         DMPlexSetSupport(rdm, newp+r, supportRef);
1901: #if 1
1902:         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);
1903:         for (p = 0; p < supportSize; ++p) {
1904:           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);
1905:         }
1906: #endif
1907:       }
1908:     }
1909:     /* Interior faces have 3 edges and 2 cells */
1910:     for (c = cStart; c < cEnd; ++c) {
1911:       PetscInt        newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8;
1912:       const PetscInt *cone, *ornt;
1913:       PetscInt        coneNew[3], orntNew[3];
1914:       PetscInt        supportNew[2];

1916:       DMPlexGetCone(dm, c, &cone);
1917:       DMPlexGetConeOrientation(dm, c, &ornt);
1918:       /* Face A: {c, a, d} */
1919:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 2);
1920:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1921:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 2);
1922:       orntNew[1] = ornt[1] < 0 ? -2 : 0;
1923:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 2);
1924:       orntNew[2] = ornt[2] < 0 ? -2 : 0;
1925:       DMPlexSetCone(rdm, newp, coneNew);
1926:       DMPlexSetConeOrientation(rdm, newp, orntNew);
1927: #if 1
1928:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1929:       for (p = 0; p < 3; ++p) {
1930:         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);
1931:       }
1932: #endif
1933:       supportNew[0] = (c - cStart)*8 + 0;
1934:       supportNew[1] = (c - cStart)*8 + 0+4;
1935:       DMPlexSetSupport(rdm, newp, supportNew);
1936: #if 1
1937:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1938:       for (p = 0; p < 2; ++p) {
1939:         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);
1940:       }
1941: #endif
1942:       ++newp;
1943:       /* Face B: {a, b, e} */
1944:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 0);
1945:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1946:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 0);
1947:       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1948:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 1);
1949:       orntNew[2] = ornt[1] < 0 ? -2 : 0;
1950:       DMPlexSetCone(rdm, newp, coneNew);
1951:       DMPlexSetConeOrientation(rdm, newp, orntNew);
1952: #if 1
1953:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1954:       for (p = 0; p < 3; ++p) {
1955:         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);
1956:       }
1957: #endif
1958:       supportNew[0] = (c - cStart)*8 + 1;
1959:       supportNew[1] = (c - cStart)*8 + 1+4;
1960:       DMPlexSetSupport(rdm, newp, supportNew);
1961: #if 1
1962:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1963:       for (p = 0; p < 2; ++p) {
1964:         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);
1965:       }
1966: #endif
1967:       ++newp;
1968:       /* Face C: {c, f, b} */
1969:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 0);
1970:       orntNew[0] = ornt[2] < 0 ? -2 : 0;
1971:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 2);
1972:       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1973:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 1);
1974:       orntNew[2] = ornt[0] < 0 ? -2 : 0;
1975:       DMPlexSetCone(rdm, newp, coneNew);
1976:       DMPlexSetConeOrientation(rdm, newp, orntNew);
1977: #if 1
1978:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1979:       for (p = 0; p < 3; ++p) {
1980:         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);
1981:       }
1982: #endif
1983:       supportNew[0] = (c - cStart)*8 + 2;
1984:       supportNew[1] = (c - cStart)*8 + 2+4;
1985:       DMPlexSetSupport(rdm, newp, supportNew);
1986: #if 1
1987:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1988:       for (p = 0; p < 2; ++p) {
1989:         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);
1990:       }
1991: #endif
1992:       ++newp;
1993:       /* Face D: {d, e, f} */
1994:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 0);
1995:       orntNew[0] = ornt[1] < 0 ? -2 : 0;
1996:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 1);
1997:       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1998:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 1);
1999:       orntNew[2] = ornt[2] < 0 ? -2 : 0;
2000:       DMPlexSetCone(rdm, newp, coneNew);
2001:       DMPlexSetConeOrientation(rdm, newp, orntNew);
2002: #if 1
2003:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2004:       for (p = 0; p < 3; ++p) {
2005:         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);
2006:       }
2007: #endif
2008:       supportNew[0] = (c - cStart)*8 + 3;
2009:       supportNew[1] = (c - cStart)*8 + 3+4;
2010:       DMPlexSetSupport(rdm, newp, supportNew);
2011: #if 1
2012:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2013:       for (p = 0; p < 2; ++p) {
2014:         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);
2015:       }
2016: #endif
2017:       ++newp;
2018:       /* Face E: {d, f, a} */
2019:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 1);
2020:       orntNew[0] = ornt[2] < 0 ? 0 : -2;
2021:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2022:       orntNew[1] = -2;
2023:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 2);
2024:       orntNew[2] = ornt[1] < 0 ? -2 : 0;
2025:       DMPlexSetCone(rdm, newp, coneNew);
2026:       DMPlexSetConeOrientation(rdm, newp, orntNew);
2027: #if 1
2028:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2029:       for (p = 0; p < 3; ++p) {
2030:         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);
2031:       }
2032: #endif
2033:       supportNew[0] = (c - cStart)*8 + 0+4;
2034:       supportNew[1] = (c - cStart)*8 + 3+4;
2035:       DMPlexSetSupport(rdm, newp, supportNew);
2036: #if 1
2037:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2038:       for (p = 0; p < 2; ++p) {
2039:         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);
2040:       }
2041: #endif
2042:       ++newp;
2043:       /* Face F: {c, a, f} */
2044:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 2);
2045:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
2046:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2047:       orntNew[1] = 0;
2048:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 0);
2049:       orntNew[2] = ornt[2] < 0 ? 0 : -2;
2050:       DMPlexSetCone(rdm, newp, coneNew);
2051:       DMPlexSetConeOrientation(rdm, newp, orntNew);
2052: #if 1
2053:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2054:       for (p = 0; p < 3; ++p) {
2055:         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);
2056:       }
2057: #endif
2058:       supportNew[0] = (c - cStart)*8 + 0+4;
2059:       supportNew[1] = (c - cStart)*8 + 2+4;
2060:       DMPlexSetSupport(rdm, newp, supportNew);
2061: #if 1
2062:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2063:       for (p = 0; p < 2; ++p) {
2064:         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);
2065:       }
2066: #endif
2067:       ++newp;
2068:       /* Face G: {e, a, f} */
2069:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 1);
2070:       orntNew[0] = ornt[1] < 0 ? -2 : 0;
2071:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2072:       orntNew[1] = 0;
2073:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 1);
2074:       orntNew[2] = ornt[3] < 0 ? 0 : -2;
2075:       DMPlexSetCone(rdm, newp, coneNew);
2076:       DMPlexSetConeOrientation(rdm, newp, orntNew);
2077: #if 1
2078:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2079:       for (p = 0; p < 3; ++p) {
2080:         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);
2081:       }
2082: #endif
2083:       supportNew[0] = (c - cStart)*8 + 1+4;
2084:       supportNew[1] = (c - cStart)*8 + 3+4;
2085:       DMPlexSetSupport(rdm, newp, supportNew);
2086: #if 1
2087:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2088:       for (p = 0; p < 2; ++p) {
2089:         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);
2090:       }
2091: #endif
2092:       ++newp;
2093:       /* Face H: {a, b, f} */
2094:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 0);
2095:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
2096:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 2);
2097:       orntNew[1] = ornt[3] < 0 ? 0 : -2;
2098:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2099:       orntNew[2] = -2;
2100:       DMPlexSetCone(rdm, newp, coneNew);
2101:       DMPlexSetConeOrientation(rdm, newp, orntNew);
2102: #if 1
2103:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2104:       for (p = 0; p < 3; ++p) {
2105:         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);
2106:       }
2107: #endif
2108:       supportNew[0] = (c - cStart)*8 + 1+4;
2109:       supportNew[1] = (c - cStart)*8 + 2+4;
2110:       DMPlexSetSupport(rdm, newp, supportNew);
2111: #if 1
2112:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2113:       for (p = 0; p < 2; ++p) {
2114:         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);
2115:       }
2116: #endif
2117:       ++newp;
2118:     }
2119:     /* Split Edges have 2 vertices and the same faces as the parent */
2120:     for (e = eStart; e < eEnd; ++e) {
2121:       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);

2123:       for (r = 0; r < 2; ++r) {
2124:         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
2125:         const PetscInt *cone, *ornt, *support;
2126:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

2128:         DMPlexGetCone(dm, e, &cone);
2129:         coneNew[0]       = vStartNew + (cone[0] - vStart);
2130:         coneNew[1]       = vStartNew + (cone[1] - vStart);
2131:         coneNew[(r+1)%2] = newv;
2132:         DMPlexSetCone(rdm, newp, coneNew);
2133: #if 1
2134:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2135:         for (p = 0; p < 2; ++p) {
2136:           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);
2137:         }
2138: #endif
2139:         DMPlexGetSupportSize(dm, e, &supportSize);
2140:         DMPlexGetSupport(dm, e, &support);
2141:         for (s = 0; s < supportSize; ++s) {
2142:           DMPlexGetConeSize(dm, support[s], &coneSize);
2143:           DMPlexGetCone(dm, support[s], &cone);
2144:           DMPlexGetConeOrientation(dm, support[s], &ornt);
2145:           for (c = 0; c < coneSize; ++c) {
2146:             if (cone[c] == e) break;
2147:           }
2148:           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
2149:         }
2150:         DMPlexSetSupport(rdm, newp, supportRef);
2151: #if 1
2152:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2153:         for (p = 0; p < supportSize; ++p) {
2154:           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);
2155:         }
2156: #endif
2157:       }
2158:     }
2159:     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
2160:     for (f = fStart; f < fEnd; ++f) {
2161:       const PetscInt *cone, *ornt, *support;
2162:       PetscInt        coneSize, supportSize, s;

2164:       DMPlexGetSupportSize(dm, f, &supportSize);
2165:       DMPlexGetSupport(dm, f, &support);
2166:       for (r = 0; r < 3; ++r) {
2167:         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
2168:         PetscInt        coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
2169:         PetscInt        fint[24] = { 1,  7, -1, -1,  0,  5,
2170:                                     -1, -1,  1,  6,  0,  4,
2171:                                      2,  5,  3,  4, -1, -1,
2172:                                     -1, -1,  3,  6,  2,  7};

2174:         DMPlexGetCone(dm, f, &cone);
2175:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
2176:         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
2177:         DMPlexSetCone(rdm, newp, coneNew);
2178: #if 1
2179:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2180:         for (p = 0; p < 2; ++p) {
2181:           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);
2182:         }
2183: #endif
2184:         supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
2185:         supportRef[1] = fStartNew + (f - fStart)*4 + 3;
2186:         for (s = 0; s < supportSize; ++s) {
2187:           DMPlexGetConeSize(dm, support[s], &coneSize);
2188:           DMPlexGetCone(dm, support[s], &cone);
2189:           DMPlexGetConeOrientation(dm, support[s], &ornt);
2190:           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
2191:           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
2192:           er = GetTetSomethingInverse_Static(ornt[c], r);
2193:           if (er == eint[c]) {
2194:             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
2195:           } else {
2196:             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
2197:             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
2198:           }
2199:         }
2200:         DMPlexSetSupport(rdm, newp, supportRef);
2201: #if 1
2202:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2203:         for (p = 0; p < intFaces; ++p) {
2204:           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);
2205:         }
2206: #endif
2207:       }
2208:     }
2209:     /* Interior edges have 2 vertices and 4 faces */
2210:     for (c = cStart; c < cEnd; ++c) {
2211:       const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2212:       const PetscInt *cone, *ornt, *fcone;
2213:       PetscInt        coneNew[2], supportNew[4], find;

2215:       DMPlexGetCone(dm, c, &cone);
2216:       DMPlexGetConeOrientation(dm, c, &ornt);
2217:       DMPlexGetCone(dm, cone[0], &fcone);
2218:       find = GetTriEdge_Static(ornt[0], 0);
2219:       coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
2220:       DMPlexGetCone(dm, cone[2], &fcone);
2221:       find = GetTriEdge_Static(ornt[2], 1);
2222:       coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
2223:       DMPlexSetCone(rdm, newp, coneNew);
2224: #if 1
2225:       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2226:       for (p = 0; p < 2; ++p) {
2227:         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);
2228:       }
2229: #endif
2230:       supportNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
2231:       supportNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
2232:       supportNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
2233:       supportNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
2234:       DMPlexSetSupport(rdm, newp, supportNew);
2235: #if 1
2236:       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2237:       for (p = 0; p < 4; ++p) {
2238:         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);
2239:       }
2240: #endif
2241:     }
2242:     /* Old vertices have identical supports */
2243:     for (v = vStart; v < vEnd; ++v) {
2244:       const PetscInt  newp = vStartNew + (v - vStart);
2245:       const PetscInt *support, *cone;
2246:       PetscInt        size, s;

2248:       DMPlexGetSupportSize(dm, v, &size);
2249:       DMPlexGetSupport(dm, v, &support);
2250:       for (s = 0; s < size; ++s) {
2251:         PetscInt r = 0;

2253:         DMPlexGetCone(dm, support[s], &cone);
2254:         if (cone[1] == v) r = 1;
2255:         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
2256:       }
2257:       DMPlexSetSupport(rdm, newp, supportRef);
2258: #if 1
2259:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2260:       for (p = 0; p < size; ++p) {
2261:         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);
2262:       }
2263: #endif
2264:     }
2265:     /* Edge vertices have 2 + face*2 + 0/1 supports */
2266:     for (e = eStart; e < eEnd; ++e) {
2267:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
2268:       const PetscInt *cone, *support;
2269:       PetscInt       *star = NULL, starSize, cellSize = 0, coneSize, size, s;

2271:       DMPlexGetSupportSize(dm, e, &size);
2272:       DMPlexGetSupport(dm, e, &support);
2273:       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
2274:       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
2275:       for (s = 0; s < size; ++s) {
2276:         PetscInt r = 0;

2278:         DMPlexGetConeSize(dm, support[s], &coneSize);
2279:         DMPlexGetCone(dm, support[s], &cone);
2280:         for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
2281:         supportRef[2+s*2+0] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
2282:         supportRef[2+s*2+1] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
2283:       }
2284:       DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
2285:       for (s = 0; s < starSize*2; s += 2) {
2286:         const PetscInt *cone, *ornt;
2287:         PetscInt        e01, e23;

2289:         if ((star[s] >= cStart) && (star[s] < cEnd)) {
2290:           /* Check edge 0-1 */
2291:           DMPlexGetCone(dm, star[s], &cone);
2292:           DMPlexGetConeOrientation(dm, star[s], &ornt);
2293:           DMPlexGetCone(dm, cone[0], &cone);
2294:           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
2295:           /* Check edge 2-3 */
2296:           DMPlexGetCone(dm, star[s], &cone);
2297:           DMPlexGetConeOrientation(dm, star[s], &ornt);
2298:           DMPlexGetCone(dm, cone[2], &cone);
2299:           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
2300:           if ((e01 == e) || (e23 == e)) {supportRef[2+size*2+cellSize++] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (star[s] - cStart);}
2301:         }
2302:       }
2303:       DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
2304:       DMPlexSetSupport(rdm, newp, supportRef);
2305: #if 1
2306:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2307:       for (p = 0; p < 2+size*2+cellSize; ++p) {
2308:         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);
2309:       }
2310: #endif
2311:     }
2312:     PetscFree(supportRef);
2313:     DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
2314:     break;
2315:   case 7:
2316:     /* Hybrid Simplicial 3D */
2317:     DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);
2318:     /* Interior cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
2319:     DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
2320:     for (c = cStart; c < cMax; ++c) {
2321:       const PetscInt  newp = cStartNew + (c - cStart)*8;
2322:       const PetscInt *cone, *ornt;
2323:       PetscInt        coneNew[4], orntNew[4];

2325:       DMPlexGetCone(dm, c, &cone);
2326:       DMPlexGetConeOrientation(dm, c, &ornt);
2327:       /* A tetrahedron: {0, a, c, d} */
2328:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
2329:       orntNew[0] = ornt[0];
2330:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
2331:       orntNew[1] = ornt[1];
2332:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
2333:       orntNew[2] = ornt[2];
2334:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 0;
2335:       orntNew[3] = 0;
2336:       DMPlexSetCone(rdm, newp+0, coneNew);
2337:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2338: #if 1
2339:       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);
2340:       for (p = 0; p < 4; ++p) {
2341:         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);
2342:       }
2343: #endif
2344:       /* B tetrahedron: {a, 1, b, e} */
2345:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
2346:       orntNew[0] = ornt[0];
2347:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
2348:       orntNew[1] = ornt[1];
2349:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 1;
2350:       orntNew[2] = 0;
2351:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
2352:       orntNew[3] = ornt[3];
2353:       DMPlexSetCone(rdm, newp+1, coneNew);
2354:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2355: #if 1
2356:       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);
2357:       for (p = 0; p < 4; ++p) {
2358:         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);
2359:       }
2360: #endif
2361:       /* C tetrahedron: {c, b, 2, f} */
2362:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
2363:       orntNew[0] = ornt[0];
2364:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 2;
2365:       orntNew[1] = 0;
2366:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
2367:       orntNew[2] = ornt[2];
2368:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
2369:       orntNew[3] = ornt[3];
2370:       DMPlexSetCone(rdm, newp+2, coneNew);
2371:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2372: #if 1
2373:       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);
2374:       for (p = 0; p < 4; ++p) {
2375:         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);
2376:       }
2377: #endif
2378:       /* D tetrahedron: {d, e, f, 3} */
2379:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 3;
2380:       orntNew[0] = 0;
2381:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
2382:       orntNew[1] = ornt[1];
2383:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
2384:       orntNew[2] = ornt[2];
2385:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
2386:       orntNew[3] = ornt[3];
2387:       DMPlexSetCone(rdm, newp+3, coneNew);
2388:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2389: #if 1
2390:       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);
2391:       for (p = 0; p < 4; ++p) {
2392:         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);
2393:       }
2394: #endif
2395:       /* A' tetrahedron: {d, a, c, f} */
2396:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 0;
2397:       orntNew[0] = -3;
2398:       coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
2399:       orntNew[1] = ornt[2] < 0 ? -(GetTetSomething_Static(ornt[2], 0)+1) : GetTetSomething_Static(ornt[2], 0);
2400:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 5;
2401:       orntNew[2] = 0;
2402:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 4;
2403:       orntNew[3] = 2;
2404:       DMPlexSetCone(rdm, newp+4, coneNew);
2405:       DMPlexSetConeOrientation(rdm, newp+4, orntNew);
2406: #if 1
2407:       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);
2408:       for (p = 0; p < 4; ++p) {
2409:         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);
2410:       }
2411: #endif
2412:       /* B' tetrahedron: {e, b, a, f} */
2413:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 1;
2414:       orntNew[0] = -3;
2415:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 6;
2416:       orntNew[1] = 1;
2417:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 7;
2418:       orntNew[2] = 0;
2419:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + 3;
2420:       orntNew[3] = ornt[3] < 0 ? -(GetTetSomething_Static(ornt[3], 0)+1) : GetTetSomething_Static(ornt[3], 0);
2421:       DMPlexSetCone(rdm, newp+5, coneNew);
2422:       DMPlexSetConeOrientation(rdm, newp+5, orntNew);
2423: #if 1
2424:       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);
2425:       for (p = 0; p < 4; ++p) {
2426:         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);
2427:       }
2428: #endif
2429:       /* C' tetrahedron: {b, f, c, a} */
2430:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 2;
2431:       orntNew[0] = -3;
2432:       coneNew[1] = fStartNew + (cone[0] - fStart)*4 + 3;
2433:       orntNew[1] = ornt[0] < 0 ? -(GetTetSomething_Static(ornt[0], 2)+1) : GetTetSomething_Static(ornt[0], 2);
2434:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 5;
2435:       orntNew[2] = -3;
2436:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 7;
2437:       orntNew[3] = -2;
2438:       DMPlexSetCone(rdm, newp+6, coneNew);
2439:       DMPlexSetConeOrientation(rdm, newp+6, orntNew);
2440: #if 1
2441:       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);
2442:       for (p = 0; p < 4; ++p) {
2443:         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);
2444:       }
2445: #endif
2446:       /* D' tetrahedron: {f, e, d, a} */
2447:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 3;
2448:       orntNew[0] = -3;
2449:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 4;
2450:       orntNew[1] = -3;
2451:       coneNew[2] = fStartNew + (cone[1] - fStart)*4 + 3;
2452:       orntNew[2] = ornt[1] < 0 ? -(GetTetSomething_Static(ornt[1], 0)+1) : GetTetSomething_Static(ornt[1], 0);
2453:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 6;
2454:       orntNew[3] = -3;
2455:       DMPlexSetCone(rdm, newp+7, coneNew);
2456:       DMPlexSetConeOrientation(rdm, newp+7, orntNew);
2457: #if 1
2458:       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);
2459:       for (p = 0; p < 4; ++p) {
2460:         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);
2461:       }
2462: #endif
2463:     }
2464:     /* Hybrid cells have 5 faces */
2465:     for (c = cMax; c < cEnd; ++c) {
2466:       const PetscInt  newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4;
2467:       const PetscInt *cone, *ornt, *fornt;
2468:       PetscInt        coneNew[5], orntNew[5];

2470:       DMPlexGetCone(dm, c, &cone);
2471:       DMPlexGetConeOrientation(dm, c, &ornt);
2472:       DMPlexGetConeOrientation(dm, cone[0], &fornt);
2473:       for (r = 0; r < 3; ++r) {
2474:         coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], r);
2475:         orntNew[0] = ornt[0];
2476:         coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], r);
2477:         orntNew[1] = ornt[1];
2478:         coneNew[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], (r+2)%3)] - fMax)*2 + (fornt[GetTriEdge_Static(ornt[0], (r+2)%3)] < 0 ? 0 : 1);
2479:         orntNew[2] = 0;
2480:         coneNew[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], r)]       - fMax)*2 + (fornt[GetTriEdge_Static(ornt[0], r)]       < 0 ? 1 : 0);
2481:         orntNew[3] = 0;
2482:         coneNew[4] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + GetTriSubface_Static(ornt[0], r);
2483:         orntNew[4] = 0;
2484:         DMPlexSetCone(rdm, newp+r, coneNew);
2485:         DMPlexSetConeOrientation(rdm, newp+r, orntNew);
2486: #if 1
2487:         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);
2488:         for (p = 0; p < 2; ++p) {
2489:           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);
2490:         }
2491:         for (p = 2; p < 5; ++p) {
2492:           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);
2493:         }
2494: #endif
2495:       }
2496:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + 3;
2497:       orntNew[0] = 0;
2498:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + 3;
2499:       orntNew[1] = 0;
2500:       coneNew[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;
2501:       orntNew[2] = 0;
2502:       coneNew[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;
2503:       orntNew[3] = 0;
2504:       coneNew[4] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;
2505:       orntNew[4] = 0;
2506:       DMPlexSetCone(rdm, newp+3, coneNew);
2507:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2508: #if 1
2509:       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);
2510:       for (p = 0; p < 2; ++p) {
2511:         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);
2512:       }
2513:       for (p = 2; p < 5; ++p) {
2514:         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);
2515:       }
2516: #endif
2517:     }
2518:     /* Split faces have 3 edges and the same cells as the parent */
2519:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
2520:     PetscMalloc1((2 + maxSupportSize*2), &supportRef);
2521:     for (f = fStart; f < fMax; ++f) {
2522:       const PetscInt  newp = fStartNew + (f - fStart)*4;
2523:       const PetscInt *cone, *ornt, *support;
2524:       PetscInt        coneNew[3], orntNew[3], coneSize, supportSize, s;

2526:       DMPlexGetCone(dm, f, &cone);
2527:       DMPlexGetConeOrientation(dm, f, &ornt);
2528:       /* A triangle */
2529:       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
2530:       orntNew[0] = ornt[0];
2531:       coneNew[1] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
2532:       orntNew[1] = -2;
2533:       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
2534:       orntNew[2] = ornt[2];
2535:       DMPlexSetCone(rdm, newp+0, coneNew);
2536:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2537: #if 1
2538:       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);
2539:       for (p = 0; p < 3; ++p) {
2540:         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);
2541:       }
2542: #endif
2543:       /* B triangle */
2544:       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
2545:       orntNew[0] = ornt[0];
2546:       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
2547:       orntNew[1] = ornt[1];
2548:       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
2549:       orntNew[2] = -2;
2550:       DMPlexSetCone(rdm, newp+1, coneNew);
2551:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2552: #if 1
2553:       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);
2554:       for (p = 0; p < 3; ++p) {
2555:         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);
2556:       }
2557: #endif
2558:       /* C triangle */
2559:       coneNew[0] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
2560:       orntNew[0] = -2;
2561:       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
2562:       orntNew[1] = ornt[1];
2563:       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
2564:       orntNew[2] = ornt[2];
2565:       DMPlexSetCone(rdm, newp+2, coneNew);
2566:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2567: #if 1
2568:       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);
2569:       for (p = 0; p < 3; ++p) {
2570:         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);
2571:       }
2572: #endif
2573:       /* D triangle */
2574:       coneNew[0] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
2575:       orntNew[0] = 0;
2576:       coneNew[1] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
2577:       orntNew[1] = 0;
2578:       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
2579:       orntNew[2] = 0;
2580:       DMPlexSetCone(rdm, newp+3, coneNew);
2581:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2582: #if 1
2583:       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);
2584:       for (p = 0; p < 3; ++p) {
2585:         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);
2586:       }
2587: #endif
2588:       DMPlexGetSupportSize(dm, f, &supportSize);
2589:       DMPlexGetSupport(dm, f, &support);
2590:       for (r = 0; r < 4; ++r) {
2591:         for (s = 0; s < supportSize; ++s) {
2592:           PetscInt subf;
2593:           DMPlexGetConeSize(dm, support[s], &coneSize);
2594:           DMPlexGetCone(dm, support[s], &cone);
2595:           DMPlexGetConeOrientation(dm, support[s], &ornt);
2596:           for (c = 0; c < coneSize; ++c) {
2597:             if (cone[c] == f) break;
2598:           }
2599:           subf = GetTriSubfaceInverse_Static(ornt[c], r);
2600:           if (support[s] < cMax) {
2601:             supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
2602:           } else {
2603:             supportRef[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (r==3 ? r : subf);
2604:           }
2605:         }
2606:         DMPlexSetSupport(rdm, newp+r, supportRef);
2607: #if 1
2608:         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);
2609:         for (p = 0; p < supportSize; ++p) {
2610:           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);
2611:         }
2612: #endif
2613:       }
2614:     }
2615:     /* Interior cell faces have 3 edges and 2 cells */
2616:     for (c = cStart; c < cMax; ++c) {
2617:       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8;
2618:       const PetscInt *cone, *ornt;
2619:       PetscInt        coneNew[3], orntNew[3];
2620:       PetscInt        supportNew[2];

2622:       DMPlexGetCone(dm, c, &cone);
2623:       DMPlexGetConeOrientation(dm, c, &ornt);
2624:       /* Face A: {c, a, d} */
2625:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 2);
2626:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
2627:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 2);
2628:       orntNew[1] = ornt[1] < 0 ? -2 : 0;
2629:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 2);
2630:       orntNew[2] = ornt[2] < 0 ? -2 : 0;
2631:       DMPlexSetCone(rdm, newp, coneNew);
2632:       DMPlexSetConeOrientation(rdm, newp, orntNew);
2633: #if 1
2634:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2635:       for (p = 0; p < 3; ++p) {
2636:         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);
2637:       }
2638: #endif
2639:       supportNew[0] = (c - cStart)*8 + 0;
2640:       supportNew[1] = (c - cStart)*8 + 0+4;
2641:       DMPlexSetSupport(rdm, newp, supportNew);
2642: #if 1
2643:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2644:       for (p = 0; p < 2; ++p) {
2645:         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);
2646:       }
2647: #endif
2648:       ++newp;
2649:       /* Face B: {a, b, e} */
2650:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 0);
2651:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
2652:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 0);
2653:       orntNew[1] = ornt[3] < 0 ? -2 : 0;
2654:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 1);
2655:       orntNew[2] = ornt[1] < 0 ? -2 : 0;
2656:       DMPlexSetCone(rdm, newp, coneNew);
2657:       DMPlexSetConeOrientation(rdm, newp, orntNew);
2658: #if 1
2659:       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);
2660:       for (p = 0; p < 3; ++p) {
2661:         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);
2662:       }
2663: #endif
2664:       supportNew[0] = (c - cStart)*8 + 1;
2665:       supportNew[1] = (c - cStart)*8 + 1+4;
2666:       DMPlexSetSupport(rdm, newp, supportNew);
2667: #if 1
2668:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2669:       for (p = 0; p < 2; ++p) {
2670:         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);
2671:       }
2672: #endif
2673:       ++newp;
2674:       /* Face C: {c, f, b} */
2675:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 0);
2676:       orntNew[0] = ornt[2] < 0 ? -2 : 0;
2677:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 2);
2678:       orntNew[1] = ornt[3] < 0 ? -2 : 0;
2679:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 1);
2680:       orntNew[2] = ornt[0] < 0 ? -2 : 0;
2681:       DMPlexSetCone(rdm, newp, coneNew);
2682:       DMPlexSetConeOrientation(rdm, newp, orntNew);
2683: #if 1
2684:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2685:       for (p = 0; p < 3; ++p) {
2686:         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);
2687:       }
2688: #endif
2689:       supportNew[0] = (c - cStart)*8 + 2;
2690:       supportNew[1] = (c - cStart)*8 + 2+4;
2691:       DMPlexSetSupport(rdm, newp, supportNew);
2692: #if 1
2693:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2694:       for (p = 0; p < 2; ++p) {
2695:         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);
2696:       }
2697: #endif
2698:       ++newp;
2699:       /* Face D: {d, e, f} */
2700:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 0);
2701:       orntNew[0] = ornt[1] < 0 ? -2 : 0;
2702:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 1);
2703:       orntNew[1] = ornt[3] < 0 ? -2 : 0;
2704:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 1);
2705:       orntNew[2] = ornt[2] < 0 ? -2 : 0;
2706:       DMPlexSetCone(rdm, newp, coneNew);
2707:       DMPlexSetConeOrientation(rdm, newp, orntNew);
2708: #if 1
2709:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2710:       for (p = 0; p < 3; ++p) {
2711:         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);
2712:       }
2713: #endif
2714:       supportNew[0] = (c - cStart)*8 + 3;
2715:       supportNew[1] = (c - cStart)*8 + 3+4;
2716:       DMPlexSetSupport(rdm, newp, supportNew);
2717: #if 1
2718:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2719:       for (p = 0; p < 2; ++p) {
2720:         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);
2721:       }
2722: #endif
2723:       ++newp;
2724:       /* Face E: {d, f, a} */
2725:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 1);
2726:       orntNew[0] = ornt[2] < 0 ? 0 : -2;
2727:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
2728:       orntNew[1] = -2;
2729:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 2);
2730:       orntNew[2] = ornt[1] < 0 ? -2 : 0;
2731:       DMPlexSetCone(rdm, newp, coneNew);
2732:       DMPlexSetConeOrientation(rdm, newp, orntNew);
2733: #if 1
2734:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2735:       for (p = 0; p < 3; ++p) {
2736:         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);
2737:       }
2738: #endif
2739:       supportNew[0] = (c - cStart)*8 + 0+4;
2740:       supportNew[1] = (c - cStart)*8 + 3+4;
2741:       DMPlexSetSupport(rdm, newp, supportNew);
2742: #if 1
2743:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2744:       for (p = 0; p < 2; ++p) {
2745:         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);
2746:       }
2747: #endif
2748:       ++newp;
2749:       /* Face F: {c, a, f} */
2750:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 2);
2751:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
2752:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
2753:       orntNew[1] = 0;
2754:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 0);
2755:       orntNew[2] = ornt[2] < 0 ? 0 : -2;
2756:       DMPlexSetCone(rdm, newp, coneNew);
2757:       DMPlexSetConeOrientation(rdm, newp, orntNew);
2758: #if 1
2759:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2760:       for (p = 0; p < 3; ++p) {
2761:         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);
2762:       }
2763: #endif
2764:       supportNew[0] = (c - cStart)*8 + 0+4;
2765:       supportNew[1] = (c - cStart)*8 + 2+4;
2766:       DMPlexSetSupport(rdm, newp, supportNew);
2767: #if 1
2768:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2769:       for (p = 0; p < 2; ++p) {
2770:         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);
2771:       }
2772: #endif
2773:       ++newp;
2774:       /* Face G: {e, a, f} */
2775:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 1);
2776:       orntNew[0] = ornt[1] < 0 ? -2 : 0;
2777:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
2778:       orntNew[1] = 0;
2779:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 1);
2780:       orntNew[2] = ornt[3] < 0 ? 0 : -2;
2781:       DMPlexSetCone(rdm, newp, coneNew);
2782:       DMPlexSetConeOrientation(rdm, newp, orntNew);
2783: #if 1
2784:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2785:       for (p = 0; p < 3; ++p) {
2786:         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);
2787:       }
2788: #endif
2789:       supportNew[0] = (c - cStart)*8 + 1+4;
2790:       supportNew[1] = (c - cStart)*8 + 3+4;
2791:       DMPlexSetSupport(rdm, newp, supportNew);
2792: #if 1
2793:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2794:       for (p = 0; p < 2; ++p) {
2795:         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);
2796:       }
2797: #endif
2798:       ++newp;
2799:       /* Face H: {a, b, f} */
2800:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 0);
2801:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
2802:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 2);
2803:       orntNew[1] = ornt[3] < 0 ? 0 : -2;
2804:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
2805:       orntNew[2] = -2;
2806:       DMPlexSetCone(rdm, newp, coneNew);
2807:       DMPlexSetConeOrientation(rdm, newp, orntNew);
2808: #if 1
2809:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2810:       for (p = 0; p < 3; ++p) {
2811:         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);
2812:       }
2813: #endif
2814:       supportNew[0] = (c - cStart)*8 + 1+4;
2815:       supportNew[1] = (c - cStart)*8 + 2+4;
2816:       DMPlexSetSupport(rdm, newp, supportNew);
2817: #if 1
2818:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
2819:       for (p = 0; p < 2; ++p) {
2820:         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);
2821:       }
2822: #endif
2823:       ++newp;
2824:     }
2825:     /* Hybrid split faces have 4 edges and same cells */
2826:     for (f = fMax; f < fEnd; ++f) {
2827:       const PetscInt *cone, *ornt, *support;
2828:       PetscInt        coneNew[4], orntNew[4];
2829:       PetscInt        supportNew[2], size, s, c;

2831:       DMPlexGetCone(dm, f, &cone);
2832:       DMPlexGetConeOrientation(dm, f, &ornt);
2833:       DMPlexGetSupportSize(dm, f, &size);
2834:       DMPlexGetSupport(dm, f, &support);
2835:       for (r = 0; r < 2; ++r) {
2836:         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;

2838:         coneNew[0]   = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
2839:         orntNew[0]   = ornt[0];
2840:         coneNew[1]   = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
2841:         orntNew[1]   = ornt[1];
2842:         coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (cone[2+r] - eMax);
2843:         orntNew[2+r] = 0;
2844:         coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd      - eMax) + (f - fMax);
2845:         orntNew[3-r] = 0;
2846:         DMPlexSetCone(rdm, newp, coneNew);
2847:         DMPlexSetConeOrientation(rdm, newp, orntNew);
2848: #if 1
2849:         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
2850:         for (p = 0; p < 2; ++p) {
2851:           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);
2852:         }
2853:         for (p = 2; p < 4; ++p) {
2854:           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);
2855:         }
2856: #endif
2857:         for (s = 0; s < size; ++s) {
2858:           const PetscInt *coneCell, *orntCell, *fornt;

2860:           DMPlexGetCone(dm, support[s], &coneCell);
2861:           DMPlexGetConeOrientation(dm, support[s], &orntCell);
2862:           for (c = 2; c < 5; ++c) if (coneCell[c] == f) break;
2863:           if (c >= 5) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of cell %d", f, support[s]);
2864:           DMPlexGetConeOrientation(dm, coneCell[0], &fornt);
2865:           supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetTriEdgeInverse_Static(orntCell[0], c-2) + (fornt[c-2] < 0 ? 1-r : r))%3;
2866:         }
2867:         DMPlexSetSupport(rdm, newp, supportNew);
2868: #if 1
2869:         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
2870:         for (p = 0; p < size; ++p) {
2871:           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);
2872:         }
2873: #endif
2874:       }
2875:     }
2876:     /* Hybrid cell faces have 4 edges and 2 cells */
2877:     for (c = cMax; c < cEnd; ++c) {
2878:       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3;
2879:       const PetscInt *cone, *ornt;
2880:       PetscInt        coneNew[4], orntNew[4];
2881:       PetscInt        supportNew[2];

2883:       DMPlexGetCone(dm, c, &cone);
2884:       DMPlexGetConeOrientation(dm, c, &ornt);
2885:       for (r = 0; r < 3; ++r) {
2886:         coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], (r+2)%3);
2887:         orntNew[0] = 0;
2888:         coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], (r+2)%3);
2889:         orntNew[1] = 0;
2890:         coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+GetTriSubface_Static(ornt[0], (r+2)%3)] - fMax);
2891:         orntNew[2] = 0;
2892:         coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+GetTriSubface_Static(ornt[0], r)]       - fMax);
2893:         orntNew[3] = 0;
2894:         DMPlexSetCone(rdm, newp+r, coneNew);
2895:         DMPlexSetConeOrientation(rdm, newp+r, orntNew);
2896: #if 1
2897:         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);
2898:         for (p = 0; p < 2; ++p) {
2899:           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);
2900:         }
2901:         for (p = 2; p < 4; ++p) {
2902:           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);
2903:         }
2904: #endif
2905:         supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetTriSubface_Static(ornt[0], r);
2906:         supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + 3;
2907:         DMPlexSetSupport(rdm, newp+r, supportNew);
2908: #if 1
2909:         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);
2910:         for (p = 0; p < 2; ++p) {
2911:           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);
2912:         }
2913: #endif
2914:       }
2915:     }
2916:     /* Interior split edges have 2 vertices and the same faces as the parent */
2917:     for (e = eStart; e < eMax; ++e) {
2918:       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);

2920:       for (r = 0; r < 2; ++r) {
2921:         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
2922:         const PetscInt *cone, *ornt, *support;
2923:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

2925:         DMPlexGetCone(dm, e, &cone);
2926:         coneNew[0]       = vStartNew + (cone[0] - vStart);
2927:         coneNew[1]       = vStartNew + (cone[1] - vStart);
2928:         coneNew[(r+1)%2] = newv;
2929:         DMPlexSetCone(rdm, newp, coneNew);
2930: #if 1
2931:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
2932:         for (p = 0; p < 2; ++p) {
2933:           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);
2934:         }
2935: #endif
2936:         DMPlexGetSupportSize(dm, e, &supportSize);
2937:         DMPlexGetSupport(dm, e, &support);
2938:         for (s = 0; s < supportSize; ++s) {
2939:           DMPlexGetConeSize(dm, support[s], &coneSize);
2940:           DMPlexGetCone(dm, support[s], &cone);
2941:           DMPlexGetConeOrientation(dm, support[s], &ornt);
2942:           for (c = 0; c < coneSize; ++c) if (cone[c] == e) break;
2943:           if (support[s] < fMax) {
2944:             supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
2945:           } else {
2946:             supportRef[s] = fStartNew + (fMax       - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
2947:           }
2948:         }
2949:         DMPlexSetSupport(rdm, newp, supportRef);
2950: #if 1
2951:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
2952:         for (p = 0; p < supportSize; ++p) {
2953:           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);
2954:         }
2955: #endif
2956:       }
2957:     }
2958:     /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
2959:     for (f = fStart; f < fMax; ++f) {
2960:       const PetscInt *cone, *ornt, *support;
2961:       PetscInt        coneSize, supportSize, s;

2963:       DMPlexGetSupportSize(dm, f, &supportSize);
2964:       DMPlexGetSupport(dm, f, &support);
2965:       for (r = 0; r < 3; ++r) {
2966:         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
2967:         PetscInt        coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
2968:         PetscInt        fint[24] = { 1,  7, -1, -1,  0,  5,
2969:                                     -1, -1,  1,  6,  0,  4,
2970:                                      2,  5,  3,  4, -1, -1,
2971:                                     -1, -1,  3,  6,  2,  7};

2973:         DMPlexGetCone(dm, f, &cone);
2974:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
2975:         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
2976:         DMPlexSetCone(rdm, newp, coneNew);
2977: #if 1
2978:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
2979:         for (p = 0; p < 2; ++p) {
2980:           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);
2981:         }
2982: #endif
2983:         supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
2984:         supportRef[1] = fStartNew + (f - fStart)*4 + 3;
2985:         for (s = 0; s < supportSize; ++s) {
2986:           DMPlexGetConeSize(dm, support[s], &coneSize);
2987:           DMPlexGetCone(dm, support[s], &cone);
2988:           DMPlexGetConeOrientation(dm, support[s], &ornt);
2989:           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
2990:           if (support[s] < cMax) {
2991:             /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
2992:             er = GetTetSomethingInverse_Static(ornt[c], r);
2993:             if (er == eint[c]) {
2994:               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
2995:             } else {
2996:               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
2997:               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
2998:             }
2999:           } else {
3000:             supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (GetTriSubfaceInverse_Static(ornt[c], r) + 1)%3;
3001:           }
3002:         }
3003:         DMPlexSetSupport(rdm, newp, supportRef);
3004: #if 1
3005:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3006:         for (p = 0; p < intFaces; ++p) {
3007:           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);
3008:         }
3009: #endif
3010:       }
3011:     }
3012:     /* Interior cell edges have 2 vertices and 4 faces */
3013:     for (c = cStart; c < cMax; ++c) {
3014:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3015:       const PetscInt *cone, *ornt, *fcone;
3016:       PetscInt        coneNew[2], supportNew[4], find;

3018:       DMPlexGetCone(dm, c, &cone);
3019:       DMPlexGetConeOrientation(dm, c, &ornt);
3020:       DMPlexGetCone(dm, cone[0], &fcone);
3021:       find = GetTriEdge_Static(ornt[0], 0);
3022:       coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
3023:       DMPlexGetCone(dm, cone[2], &fcone);
3024:       find = GetTriEdge_Static(ornt[2], 1);
3025:       coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
3026:       DMPlexSetCone(rdm, newp, coneNew);
3027: #if 1
3028:       if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3029:       for (p = 0; p < 2; ++p) {
3030:         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);
3031:       }
3032: #endif
3033:       supportNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
3034:       supportNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
3035:       supportNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
3036:       supportNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
3037:       DMPlexSetSupport(rdm, newp, supportNew);
3038: #if 1
3039:       if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3040:       for (p = 0; p < 4; ++p) {
3041:         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);
3042:       }
3043: #endif
3044:     }
3045:     /* Hybrid edges have two vertices and the same faces */
3046:     for (e = eMax; e < eEnd; ++e) {
3047:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
3048:       const PetscInt *cone, *support, *fcone;
3049:       PetscInt        coneNew[2], size, fsize, s;

3051:       DMPlexGetCone(dm, e, &cone);
3052:       DMPlexGetSupportSize(dm, e, &size);
3053:       DMPlexGetSupport(dm, e, &support);
3054:       coneNew[0] = vStartNew + (cone[0] - vStart);
3055:       coneNew[1] = vStartNew + (cone[1] - vStart);
3056:       DMPlexSetCone(rdm, newp, coneNew);
3057: #if 1
3058:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
3059:       for (p = 0; p < 2; ++p) {
3060:         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);
3061:       }
3062: #endif
3063:       for (s = 0; s < size; ++s) {
3064:         DMPlexGetConeSize(dm, support[s], &fsize);
3065:         DMPlexGetCone(dm, support[s], &fcone);
3066:         for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
3067:         if ((c < 2) || (c > 3)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge %d not found in cone of face %d", e, support[s]);
3068:         supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + c-2;
3069:       }
3070:       DMPlexSetSupport(rdm, newp, supportRef);
3071: #if 1
3072:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
3073:       for (p = 0; p < size; ++p) {
3074:         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);
3075:       }
3076: #endif
3077:     }
3078:     /* Hybrid face edges have 2 vertices and 2+2*cells faces */
3079:     for (f = fMax; f < fEnd; ++f) {
3080:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
3081:       const PetscInt *cone, *support, *ccone, *cornt;
3082:       PetscInt        coneNew[2], size, csize, s;

3084:       DMPlexGetCone(dm, f, &cone);
3085:       DMPlexGetSupportSize(dm, f, &size);
3086:       DMPlexGetSupport(dm, f, &support);
3087:       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
3088:       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
3089:       DMPlexSetCone(rdm, newp, coneNew);
3090: #if 1
3091:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
3092:       for (p = 0; p < 2; ++p) {
3093:         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);
3094:       }
3095: #endif
3096:       supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 0;
3097:       supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 1;
3098:       for (s = 0; s < size; ++s) {
3099:         DMPlexGetConeSize(dm, support[s], &csize);
3100:         DMPlexGetCone(dm, support[s], &ccone);
3101:         DMPlexGetConeOrientation(dm, support[s], &cornt);
3102:         for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
3103:         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]);
3104:         supportRef[2+s*2+0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + GetTriSubfaceInverse_Static(cornt[0], c-2);
3105:         supportRef[2+s*2+1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (GetTriSubfaceInverse_Static(cornt[0], c-2) + 1)%3;
3106:       }
3107:       DMPlexSetSupport(rdm, newp, supportRef);
3108: #if 1
3109:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
3110:       for (p = 0; p < 2+size*2; ++p) {
3111:         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);
3112:       }
3113: #endif
3114:     }
3115:     /* Interior vertices have identical supports */
3116:     for (v = vStart; v < vEnd; ++v) {
3117:       const PetscInt  newp = vStartNew + (v - vStart);
3118:       const PetscInt *support, *cone;
3119:       PetscInt        size, s;

3121:       DMPlexGetSupportSize(dm, v, &size);
3122:       DMPlexGetSupport(dm, v, &support);
3123:       for (s = 0; s < size; ++s) {
3124:         PetscInt r = 0;

3126:         DMPlexGetCone(dm, support[s], &cone);
3127:         if (cone[1] == v) r = 1;
3128:         if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
3129:         else                   supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (support[s] - eMax);
3130:       }
3131:       DMPlexSetSupport(rdm, newp, supportRef);
3132: #if 1
3133:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3134:       for (p = 0; p < size; ++p) {
3135:         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);
3136:       }
3137: #endif
3138:     }
3139:     /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
3140:     for (e = eStart; e < eMax; ++e) {
3141:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
3142:       const PetscInt *cone, *support;
3143:       PetscInt       *star = NULL, starSize, faceSize = 0, cellSize = 0, coneSize, size, s;

3145:       DMPlexGetSupportSize(dm, e, &size);
3146:       DMPlexGetSupport(dm, e, &support);
3147:       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
3148:       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
3149:       for (s = 0; s < size; ++s) {
3150:         PetscInt r = 0;

3152:         if (support[s] < fMax) {
3153:           DMPlexGetConeSize(dm, support[s], &coneSize);
3154:           DMPlexGetCone(dm, support[s], &cone);
3155:           for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
3156:           supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
3157:           supportRef[2+faceSize+1] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
3158:           faceSize += 2;
3159:         } else {
3160:           supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (fMax       - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (support[s] - fMax);
3161:           ++faceSize;
3162:         }
3163:       }
3164:       DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
3165:       for (s = 0; s < starSize*2; s += 2) {
3166:         const PetscInt *cone, *ornt;
3167:         PetscInt        e01, e23;

3169:         if ((star[s] >= cStart) && (star[s] < cMax)) {
3170:           /* Check edge 0-1 */
3171:           DMPlexGetCone(dm, star[s], &cone);
3172:           DMPlexGetConeOrientation(dm, star[s], &ornt);
3173:           DMPlexGetCone(dm, cone[0], &cone);
3174:           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
3175:           /* Check edge 2-3 */
3176:           DMPlexGetCone(dm, star[s], &cone);
3177:           DMPlexGetConeOrientation(dm, star[s], &ornt);
3178:           DMPlexGetCone(dm, cone[2], &cone);
3179:           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
3180:           if ((e01 == e) || (e23 == e)) {supportRef[2+faceSize+cellSize++] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (star[s] - cStart);}
3181:         }
3182:       }
3183:       DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
3184:       DMPlexSetSupport(rdm, newp, supportRef);
3185: #if 1
3186:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3187:       for (p = 0; p < 2+faceSize+cellSize; ++p) {
3188:         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);
3189:       }
3190: #endif
3191:     }
3192:     PetscFree(supportRef);
3193:     DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
3194:     break;
3195:   case 6:
3196:     /* Hex 3D */
3197:     /*
3198:      Bottom (viewed from top)    Top
3199:      1---------2---------2       7---------2---------6
3200:      |         |         |       |         |         |
3201:      |    B    2    C    |       |    H    2    G    |
3202:      |         |         |       |         |         |
3203:      3----3----0----1----1       3----3----0----1----1
3204:      |         |         |       |         |         |
3205:      |    A    0    D    |       |    E    0    F    |
3206:      |         |         |       |         |         |
3207:      0---------0---------3       4---------0---------5
3208:      */
3209:     /* All cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
3210:     for (c = cStart; c < cEnd; ++c) {
3211:       const PetscInt  newp = (c - cStart)*8;
3212:       const PetscInt *cone, *ornt;
3213:       PetscInt        coneNew[6], orntNew[6];

3215:       DMPlexGetCone(dm, c, &cone);
3216:       DMPlexGetConeOrientation(dm, c, &ornt);
3217:       /* A hex */
3218:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
3219:       orntNew[0] = ornt[0];
3220:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
3221:       orntNew[1] = 0;
3222:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
3223:       orntNew[2] = ornt[2];
3224:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
3225:       orntNew[3] = 0;
3226:       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
3227:       orntNew[4] = 0;
3228:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
3229:       orntNew[5] = ornt[5];
3230:       DMPlexSetCone(rdm, newp+0, coneNew);
3231:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
3232: #if 1
3233:       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);
3234:       for (p = 0; p < 6; ++p) {
3235:         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);
3236:       }
3237: #endif
3238:       /* B hex */
3239:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
3240:       orntNew[0] = ornt[0];
3241:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
3242:       orntNew[1] = 0;
3243:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
3244:       orntNew[2] = -1;
3245:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
3246:       orntNew[3] = ornt[3];
3247:       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
3248:       orntNew[4] = 0;
3249:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
3250:       orntNew[5] = ornt[5];
3251:       DMPlexSetCone(rdm, newp+1, coneNew);
3252:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
3253: #if 1
3254:       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);
3255:       for (p = 0; p < 6; ++p) {
3256:         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);
3257:       }
3258: #endif
3259:       /* C hex */
3260:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
3261:       orntNew[0] = ornt[0];
3262:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
3263:       orntNew[1] = 0;
3264:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
3265:       orntNew[2] = -1;
3266:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
3267:       orntNew[3] = ornt[3];
3268:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
3269:       orntNew[4] = ornt[4];
3270:       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
3271:       orntNew[5] = -4;
3272:       DMPlexSetCone(rdm, newp+2, coneNew);
3273:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
3274: #if 1
3275:       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);
3276:       for (p = 0; p < 6; ++p) {
3277:         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);
3278:       }
3279: #endif
3280:       /* D hex */
3281:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
3282:       orntNew[0] = ornt[0];
3283:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
3284:       orntNew[1] = 0;
3285:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
3286:       orntNew[2] = ornt[2];
3287:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
3288:       orntNew[3] = 0;
3289:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
3290:       orntNew[4] = ornt[4];
3291:       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
3292:       orntNew[5] = -4;
3293:       DMPlexSetCone(rdm, newp+3, coneNew);
3294:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3295: #if 1
3296:       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);
3297:       for (p = 0; p < 6; ++p) {
3298:         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);
3299:       }
3300: #endif
3301:       /* E hex */
3302:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
3303:       orntNew[0] = -4;
3304:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
3305:       orntNew[1] = ornt[1];
3306:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
3307:       orntNew[2] = ornt[2];
3308:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
3309:       orntNew[3] = 0;
3310:       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
3311:       orntNew[4] = -1;
3312:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
3313:       orntNew[5] = ornt[5];
3314:       DMPlexSetCone(rdm, newp+4, coneNew);
3315:       DMPlexSetConeOrientation(rdm, newp+4, orntNew);
3316: #if 1
3317:       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);
3318:       for (p = 0; p < 6; ++p) {
3319:         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);
3320:       }
3321: #endif
3322:       /* F hex */
3323:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
3324:       orntNew[0] = -4;
3325:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
3326:       orntNew[1] = ornt[1];
3327:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
3328:       orntNew[2] = ornt[2];
3329:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
3330:       orntNew[3] = -1;
3331:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
3332:       orntNew[4] = ornt[4];
3333:       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
3334:       orntNew[5] = 1;
3335:       DMPlexSetCone(rdm, newp+5, coneNew);
3336:       DMPlexSetConeOrientation(rdm, newp+5, orntNew);
3337: #if 1
3338:       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);
3339:       for (p = 0; p < 6; ++p) {
3340:         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);
3341:       }
3342: #endif
3343:       /* G hex */
3344:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
3345:       orntNew[0] = -4;
3346:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
3347:       orntNew[1] = ornt[1];
3348:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
3349:       orntNew[2] = 0;
3350:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
3351:       orntNew[3] = ornt[3];
3352:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
3353:       orntNew[4] = ornt[4];
3354:       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
3355:       orntNew[5] = -3;
3356:       DMPlexSetCone(rdm, newp+6, coneNew);
3357:       DMPlexSetConeOrientation(rdm, newp+6, orntNew);
3358: #if 1
3359:       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);
3360:       for (p = 0; p < 6; ++p) {
3361:         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);
3362:       }
3363: #endif
3364:       /* H hex */
3365:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
3366:       orntNew[0] = -4;
3367:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
3368:       orntNew[1] = ornt[1];
3369:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
3370:       orntNew[2] = -1;
3371:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
3372:       orntNew[3] = ornt[3];
3373:       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
3374:       orntNew[4] = 3;
3375:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
3376:       orntNew[5] = ornt[5];
3377:       DMPlexSetCone(rdm, newp+7, coneNew);
3378:       DMPlexSetConeOrientation(rdm, newp+7, orntNew);
3379: #if 1
3380:       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);
3381:       for (p = 0; p < 6; ++p) {
3382:         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);
3383:       }
3384: #endif
3385:     }
3386:     /* Split faces have 4 edges and the same cells as the parent */
3387:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
3388:     PetscMalloc1((4 + maxSupportSize*2), &supportRef);
3389:     for (f = fStart; f < fEnd; ++f) {
3390:       for (r = 0; r < 4; ++r) {
3391:         /* TODO: This can come from GetFaces_Internal() */
3392:         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};
3393:         const PetscInt  newp = fStartNew + (f - fStart)*4 + r;
3394:         const PetscInt *cone, *ornt, *support;
3395:         PetscInt        coneNew[4], orntNew[4], coneSize, c, supportSize, s;

3397:         DMPlexGetCone(dm, f, &cone);
3398:         DMPlexGetConeOrientation(dm, f, &ornt);
3399:         coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
3400:         orntNew[(r+3)%4] = ornt[(r+3)%4];
3401:         coneNew[(r+0)%4] = eStartNew + (cone[r]       - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
3402:         orntNew[(r+0)%4] = ornt[r];
3403:         coneNew[(r+1)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
3404:         orntNew[(r+1)%4] = 0;
3405:         coneNew[(r+2)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + (r+3)%4;
3406:         orntNew[(r+2)%4] = -2;
3407:         DMPlexSetCone(rdm, newp, coneNew);
3408:         DMPlexSetConeOrientation(rdm, newp, orntNew);
3409: #if 1
3410:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3411:         for (p = 0; p < 4; ++p) {
3412:           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);
3413:         }
3414: #endif
3415:         DMPlexGetSupportSize(dm, f, &supportSize);
3416:         DMPlexGetSupport(dm, f, &support);
3417:         for (s = 0; s < supportSize; ++s) {
3418:           DMPlexGetConeSize(dm, support[s], &coneSize);
3419:           DMPlexGetCone(dm, support[s], &cone);
3420:           DMPlexGetConeOrientation(dm, support[s], &ornt);
3421:           for (c = 0; c < coneSize; ++c) {
3422:             if (cone[c] == f) break;
3423:           }
3424:           supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+GetQuadSubfaceInverse_Static(ornt[c], r)];
3425:         }
3426:         DMPlexSetSupport(rdm, newp, supportRef);
3427: #if 1
3428:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3429:         for (p = 0; p < supportSize; ++p) {
3430:           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);
3431:         }
3432: #endif
3433:       }
3434:     }
3435:     /* Interior faces have 4 edges and 2 cells */
3436:     for (c = cStart; c < cEnd; ++c) {
3437:       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};
3438:       const PetscInt *cone, *ornt;
3439:       PetscInt        newp, coneNew[4], orntNew[4], supportNew[2];

3441:       DMPlexGetCone(dm, c, &cone);
3442:       DMPlexGetConeOrientation(dm, c, &ornt);
3443:       /* A-D face */
3444:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0;
3445:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
3446:       orntNew[0] = 0;
3447:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
3448:       orntNew[1] = 0;
3449:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
3450:       orntNew[2] = -2;
3451:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
3452:       orntNew[3] = -2;
3453:       DMPlexSetCone(rdm, newp, coneNew);
3454:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3455: #if 1
3456:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3457:       for (p = 0; p < 4; ++p) {
3458:         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);
3459:       }
3460: #endif
3461:       /* C-D face */
3462:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1;
3463:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
3464:       orntNew[0] = 0;
3465:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
3466:       orntNew[1] = 0;
3467:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
3468:       orntNew[2] = -2;
3469:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
3470:       orntNew[3] = -2;
3471:       DMPlexSetCone(rdm, newp, coneNew);
3472:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3473: #if 1
3474:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3475:       for (p = 0; p < 4; ++p) {
3476:         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);
3477:       }
3478: #endif
3479:       /* B-C face */
3480:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2;
3481:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
3482:       orntNew[0] = -2;
3483:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
3484:       orntNew[1] = 0;
3485:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
3486:       orntNew[2] = 0;
3487:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
3488:       orntNew[3] = -2;
3489:       DMPlexSetCone(rdm, newp, coneNew);
3490:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3491: #if 1
3492:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3493:       for (p = 0; p < 4; ++p) {
3494:         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);
3495:       }
3496: #endif
3497:       /* A-B face */
3498:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3;
3499:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
3500:       orntNew[0] = -2;
3501:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
3502:       orntNew[1] = 0;
3503:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
3504:       orntNew[2] = 0;
3505:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
3506:       orntNew[3] = -2;
3507:       DMPlexSetCone(rdm, newp, coneNew);
3508:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3509: #if 1
3510:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3511:       for (p = 0; p < 4; ++p) {
3512:         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);
3513:       }
3514: #endif
3515:       /* E-F face */
3516:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4;
3517:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
3518:       orntNew[0] = -2;
3519:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
3520:       orntNew[1] = -2;
3521:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
3522:       orntNew[2] = 0;
3523:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
3524:       orntNew[3] = 0;
3525:       DMPlexSetCone(rdm, newp, coneNew);
3526:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3527: #if 1
3528:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3529:       for (p = 0; p < 4; ++p) {
3530:         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);
3531:       }
3532: #endif
3533:       /* F-G face */
3534:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5;
3535:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
3536:       orntNew[0] = -2;
3537:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
3538:       orntNew[1] = -2;
3539:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
3540:       orntNew[2] = 0;
3541:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
3542:       orntNew[3] = 0;
3543:       DMPlexSetCone(rdm, newp, coneNew);
3544:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3545: #if 1
3546:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3547:       for (p = 0; p < 4; ++p) {
3548:         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);
3549:       }
3550: #endif
3551:       /* G-H face */
3552:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6;
3553:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
3554:       orntNew[0] = -2;
3555:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
3556:       orntNew[1] = 0;
3557:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
3558:       orntNew[2] = 0;
3559:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
3560:       orntNew[3] = -2;
3561:       DMPlexSetCone(rdm, newp, coneNew);
3562:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3563: #if 1
3564:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3565:       for (p = 0; p < 4; ++p) {
3566:         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);
3567:       }
3568: #endif
3569:       /* E-H face */
3570:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7;
3571:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
3572:       orntNew[0] = -2;
3573:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
3574:       orntNew[1] = -2;
3575:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
3576:       orntNew[2] = 0;
3577:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
3578:       orntNew[3] = 0;
3579:       DMPlexSetCone(rdm, newp, coneNew);
3580:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3581: #if 1
3582:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3583:       for (p = 0; p < 4; ++p) {
3584:         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);
3585:       }
3586: #endif
3587:       /* A-E face */
3588:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8;
3589:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
3590:       orntNew[0] = 0;
3591:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
3592:       orntNew[1] = 0;
3593:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
3594:       orntNew[2] = -2;
3595:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
3596:       orntNew[3] = -2;
3597:       DMPlexSetCone(rdm, newp, coneNew);
3598:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3599: #if 1
3600:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3601:       for (p = 0; p < 4; ++p) {
3602:         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);
3603:       }
3604: #endif
3605:       /* D-F face */
3606:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9;
3607:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
3608:       orntNew[0] = -2;
3609:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
3610:       orntNew[1] = 0;
3611:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
3612:       orntNew[2] = 0;
3613:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
3614:       orntNew[3] = -2;
3615:       DMPlexSetCone(rdm, newp, coneNew);
3616:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3617: #if 1
3618:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3619:       for (p = 0; p < 4; ++p) {
3620:         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);
3621:       }
3622: #endif
3623:       /* C-G face */
3624:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10;
3625:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
3626:       orntNew[0] = -2;
3627:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
3628:       orntNew[1] = -2;
3629:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
3630:       orntNew[2] = 0;
3631:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
3632:       orntNew[3] = 0;
3633:       DMPlexSetCone(rdm, newp, coneNew);
3634:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3635: #if 1
3636:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3637:       for (p = 0; p < 4; ++p) {
3638:         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);
3639:       }
3640: #endif
3641:       /* B-H face */
3642:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11;
3643:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
3644:       orntNew[0] = 0;
3645:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
3646:       orntNew[1] = -2;
3647:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
3648:       orntNew[2] = -2;
3649:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
3650:       orntNew[3] = 0;
3651:       DMPlexSetCone(rdm, newp, coneNew);
3652:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3653: #if 1
3654:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3655:       for (p = 0; p < 4; ++p) {
3656:         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);
3657:       }
3658: #endif
3659:       for (r = 0; r < 12; ++r) {
3660:         newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
3661:         supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
3662:         supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
3663:         DMPlexSetSupport(rdm, newp, supportNew);
3664: #if 1
3665:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3666:         for (p = 0; p < 2; ++p) {
3667:           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);
3668:         }
3669: #endif
3670:       }
3671:     }
3672:     /* Split edges have 2 vertices and the same faces as the parent */
3673:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
3674:     for (e = eStart; e < eEnd; ++e) {
3675:       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);

3677:       for (r = 0; r < 2; ++r) {
3678:         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
3679:         const PetscInt *cone, *ornt, *support;
3680:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

3682:         DMPlexGetCone(dm, e, &cone);
3683:         coneNew[0]       = vStartNew + (cone[0] - vStart);
3684:         coneNew[1]       = vStartNew + (cone[1] - vStart);
3685:         coneNew[(r+1)%2] = newv;
3686:         DMPlexSetCone(rdm, newp, coneNew);
3687: #if 1
3688:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3689:         for (p = 0; p < 2; ++p) {
3690:           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);
3691:         }
3692: #endif
3693:         DMPlexGetSupportSize(dm, e, &supportSize);
3694:         DMPlexGetSupport(dm, e, &support);
3695:         for (s = 0; s < supportSize; ++s) {
3696:           DMPlexGetConeSize(dm, support[s], &coneSize);
3697:           DMPlexGetCone(dm, support[s], &cone);
3698:           DMPlexGetConeOrientation(dm, support[s], &ornt);
3699:           for (c = 0; c < coneSize; ++c) {
3700:             if (cone[c] == e) break;
3701:           }
3702:           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
3703:         }
3704:         DMPlexSetSupport(rdm, newp, supportRef);
3705: #if 1
3706:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3707:         for (p = 0; p < supportSize; ++p) {
3708:           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);
3709:         }
3710: #endif
3711:       }
3712:     }
3713:     /* Face edges have 2 vertices and 2+cells faces */
3714:     for (f = fStart; f < fEnd; ++f) {
3715:       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};
3716:       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
3717:       const PetscInt *cone, *coneCell, *orntCell, *support;
3718:       PetscInt        coneNew[2], coneSize, c, supportSize, s;

3720:       DMPlexGetCone(dm, f, &cone);
3721:       for (r = 0; r < 4; ++r) {
3722:         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;

3724:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
3725:         coneNew[1] = newv;
3726:         DMPlexSetCone(rdm, newp, coneNew);
3727: #if 1
3728:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3729:         for (p = 0; p < 2; ++p) {
3730:           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);
3731:         }
3732: #endif
3733:         DMPlexGetSupportSize(dm, f, &supportSize);
3734:         DMPlexGetSupport(dm, f, &support);
3735:         supportRef[0] = fStartNew + (f - fStart)*4 + r;
3736:         supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
3737:         for (s = 0; s < supportSize; ++s) {
3738:           DMPlexGetConeSize(dm, support[s], &coneSize);
3739:           DMPlexGetCone(dm, support[s], &coneCell);
3740:           DMPlexGetConeOrientation(dm, support[s], &orntCell);
3741:           for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
3742:           supportRef[2+s] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
3743:         }
3744:         DMPlexSetSupport(rdm, newp, supportRef);
3745: #if 1
3746:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3747:         for (p = 0; p < 2+supportSize; ++p) {
3748:           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);
3749:         }
3750: #endif
3751:       }
3752:     }
3753:     /* Cell edges have 2 vertices and 4 faces */
3754:     for (c = cStart; c < cEnd; ++c) {
3755:       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};
3756:       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
3757:       const PetscInt *cone;
3758:       PetscInt        coneNew[2], supportNew[4];

3760:       DMPlexGetCone(dm, c, &cone);
3761:       for (r = 0; r < 6; ++r) {
3762:         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;

3764:         coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
3765:         coneNew[1] = newv;
3766:         DMPlexSetCone(rdm, newp, coneNew);
3767: #if 1
3768:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3769:         for (p = 0; p < 2; ++p) {
3770:           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);
3771:         }
3772: #endif
3773:         for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
3774:         DMPlexSetSupport(rdm, newp, supportNew);
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 < 4; ++p) {
3778:           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);
3779:         }
3780: #endif
3781:       }
3782:     }
3783:     /* Old vertices have identical supports */
3784:     for (v = vStart; v < vEnd; ++v) {
3785:       const PetscInt  newp = vStartNew + (v - vStart);
3786:       const PetscInt *support, *cone;
3787:       PetscInt        size, s;

3789:       DMPlexGetSupportSize(dm, v, &size);
3790:       DMPlexGetSupport(dm, v, &support);
3791:       for (s = 0; s < size; ++s) {
3792:         PetscInt r = 0;

3794:         DMPlexGetCone(dm, support[s], &cone);
3795:         if (cone[1] == v) r = 1;
3796:         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
3797:       }
3798:       DMPlexSetSupport(rdm, newp, supportRef);
3799: #if 1
3800:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3801:       for (p = 0; p < size; ++p) {
3802:         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);
3803:       }
3804: #endif
3805:     }
3806:     /* Edge vertices have 2 + faces supports */
3807:     for (e = eStart; e < eEnd; ++e) {
3808:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
3809:       const PetscInt *cone, *support;
3810:       PetscInt        size, s;

3812:       DMPlexGetSupportSize(dm, e, &size);
3813:       DMPlexGetSupport(dm, e, &support);
3814:       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
3815:       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
3816:       for (s = 0; s < size; ++s) {
3817:         PetscInt r;

3819:         DMPlexGetCone(dm, support[s], &cone);
3820:         for (r = 0; r < 4; ++r) if (cone[r] == e) break;
3821:         supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*4 + r;
3822:       }
3823:       DMPlexSetSupport(rdm, newp, supportRef);
3824: #if 1
3825:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3826:       for (p = 0; p < 2+size; ++p) {
3827:         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);
3828:       }
3829: #endif
3830:     }
3831:     /* Face vertices have 4 + cells supports */
3832:     for (f = fStart; f < fEnd; ++f) {
3833:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
3834:       const PetscInt *cone, *support;
3835:       PetscInt        size, s;

3837:       DMPlexGetSupportSize(dm, f, &size);
3838:       DMPlexGetSupport(dm, f, &support);
3839:       for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eEnd - eStart)*2 +  (f - fStart)*4 + r;
3840:       for (s = 0; s < size; ++s) {
3841:         PetscInt r;

3843:         DMPlexGetCone(dm, support[s], &cone);
3844:         for (r = 0; r < 6; ++r) if (cone[r] == f) break;
3845:         supportRef[4+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (support[s] - cStart)*6 + r;
3846:       }
3847:       DMPlexSetSupport(rdm, newp, supportRef);
3848: #if 1
3849:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3850:       for (p = 0; p < 4+size; ++p) {
3851:         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);
3852:       }
3853: #endif
3854:     }
3855:     /* Cell vertices have 6 supports */
3856:     for (c = cStart; c < cEnd; ++c) {
3857:       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
3858:       PetscInt       supportNew[6];

3860:       for (r = 0; r < 6; ++r) {
3861:         supportNew[r] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
3862:       }
3863:       DMPlexSetSupport(rdm, newp, supportNew);
3864:     }
3865:     PetscFree(supportRef);
3866:     break;
3867:   case 8:
3868:     /* Hybrid Hex 3D */
3869:     DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);
3870:     /*
3871:      Bottom (viewed from top)    Top
3872:      1---------2---------2       7---------2---------6
3873:      |         |         |       |         |         |
3874:      |    B    2    C    |       |    H    2    G    |
3875:      |         |         |       |         |         |
3876:      3----3----0----1----1       3----3----0----1----1
3877:      |         |         |       |         |         |
3878:      |    A    0    D    |       |    E    0    F    |
3879:      |         |         |       |         |         |
3880:      0---------0---------3       4---------0---------5
3881:      */
3882:     /* Interior cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
3883:     for (c = cStart; c < cMax; ++c) {
3884:       const PetscInt  newp = (c - cStart)*8;
3885:       const PetscInt *cone, *ornt;
3886:       PetscInt        coneNew[6], orntNew[6];

3888:       DMPlexGetCone(dm, c, &cone);
3889:       DMPlexGetConeOrientation(dm, c, &ornt);
3890:       /* A hex */
3891:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
3892:       orntNew[0] = ornt[0];
3893:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
3894:       orntNew[1] = 0;
3895:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
3896:       orntNew[2] = ornt[2];
3897:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
3898:       orntNew[3] = 0;
3899:       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
3900:       orntNew[4] = 0;
3901:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
3902:       orntNew[5] = ornt[5];
3903:       DMPlexSetCone(rdm, newp+0, coneNew);
3904:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
3905: #if 1
3906:       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);
3907:       for (p = 0; p < 6; ++p) {
3908:         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);
3909:       }
3910: #endif
3911:       /* B hex */
3912:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
3913:       orntNew[0] = ornt[0];
3914:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
3915:       orntNew[1] = 0;
3916:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
3917:       orntNew[2] = -1;
3918:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
3919:       orntNew[3] = ornt[3];
3920:       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
3921:       orntNew[4] = 0;
3922:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
3923:       orntNew[5] = ornt[5];
3924:       DMPlexSetCone(rdm, newp+1, coneNew);
3925:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
3926: #if 1
3927:       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);
3928:       for (p = 0; p < 6; ++p) {
3929:         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);
3930:       }
3931: #endif
3932:       /* C hex */
3933:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
3934:       orntNew[0] = ornt[0];
3935:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
3936:       orntNew[1] = 0;
3937:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
3938:       orntNew[2] = -1;
3939:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
3940:       orntNew[3] = ornt[3];
3941:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
3942:       orntNew[4] = ornt[4];
3943:       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
3944:       orntNew[5] = -4;
3945:       DMPlexSetCone(rdm, newp+2, coneNew);
3946:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
3947: #if 1
3948:       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);
3949:       for (p = 0; p < 6; ++p) {
3950:         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);
3951:       }
3952: #endif
3953:       /* D hex */
3954:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
3955:       orntNew[0] = ornt[0];
3956:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
3957:       orntNew[1] = 0;
3958:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
3959:       orntNew[2] = ornt[2];
3960:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
3961:       orntNew[3] = 0;
3962:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
3963:       orntNew[4] = ornt[4];
3964:       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
3965:       orntNew[5] = -4;
3966:       DMPlexSetCone(rdm, newp+3, coneNew);
3967:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3968: #if 1
3969:       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);
3970:       for (p = 0; p < 6; ++p) {
3971:         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);
3972:       }
3973: #endif
3974:       /* E hex */
3975:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
3976:       orntNew[0] = -4;
3977:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
3978:       orntNew[1] = ornt[1];
3979:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
3980:       orntNew[2] = ornt[2];
3981:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
3982:       orntNew[3] = 0;
3983:       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
3984:       orntNew[4] = -1;
3985:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
3986:       orntNew[5] = ornt[5];
3987:       DMPlexSetCone(rdm, newp+4, coneNew);
3988:       DMPlexSetConeOrientation(rdm, newp+4, orntNew);
3989: #if 1
3990:       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);
3991:       for (p = 0; p < 6; ++p) {
3992:         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);
3993:       }
3994: #endif
3995:       /* F hex */
3996:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
3997:       orntNew[0] = -4;
3998:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
3999:       orntNew[1] = ornt[1];
4000:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
4001:       orntNew[2] = ornt[2];
4002:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
4003:       orntNew[3] = -1;
4004:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
4005:       orntNew[4] = ornt[4];
4006:       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
4007:       orntNew[5] = 1;
4008:       DMPlexSetCone(rdm, newp+5, coneNew);
4009:       DMPlexSetConeOrientation(rdm, newp+5, orntNew);
4010: #if 1
4011:       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);
4012:       for (p = 0; p < 6; ++p) {
4013:         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);
4014:       }
4015: #endif
4016:       /* G hex */
4017:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
4018:       orntNew[0] = -4;
4019:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
4020:       orntNew[1] = ornt[1];
4021:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
4022:       orntNew[2] = 0;
4023:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
4024:       orntNew[3] = ornt[3];
4025:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
4026:       orntNew[4] = ornt[4];
4027:       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
4028:       orntNew[5] = -3;
4029:       DMPlexSetCone(rdm, newp+6, coneNew);
4030:       DMPlexSetConeOrientation(rdm, newp+6, orntNew);
4031: #if 1
4032:       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);
4033:       for (p = 0; p < 6; ++p) {
4034:         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);
4035:       }
4036: #endif
4037:       /* H hex */
4038:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
4039:       orntNew[0] = -4;
4040:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
4041:       orntNew[1] = ornt[1];
4042:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
4043:       orntNew[2] = -1;
4044:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
4045:       orntNew[3] = ornt[3];
4046:       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
4047:       orntNew[4] = 3;
4048:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
4049:       orntNew[5] = ornt[5];
4050:       DMPlexSetCone(rdm, newp+7, coneNew);
4051:       DMPlexSetConeOrientation(rdm, newp+7, orntNew);
4052: #if 1
4053:       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);
4054:       for (p = 0; p < 6; ++p) {
4055:         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);
4056:       }
4057: #endif
4058:     }
4059:     /* Hybrid cells have 6 faces: Front, Back, Sides */
4060:     /*
4061:      3---------2---------2
4062:      |         |         |
4063:      |    D    2    C    |
4064:      |         |         |
4065:      3----3----0----1----1
4066:      |         |         |
4067:      |    A    0    B    |
4068:      |         |         |
4069:      0---------0---------1
4070:      */
4071:     for (c = cMax; c < cEnd; ++c) {
4072:       const PetscInt  newp = (cMax - cStart)*8 + (c - cMax)*4;
4073:       const PetscInt *cone, *ornt, *fornt;
4074:       PetscInt        coneNew[6], orntNew[6];

4076:       DMPlexGetCone(dm, c, &cone);
4077:       DMPlexGetConeOrientation(dm, c, &ornt);
4078:       DMPlexGetConeOrientation(dm, cone[0], &fornt);
4079:       for (r = 0; r < 4; ++r) {
4080:         PetscInt subfA = GetQuadSubface_Static(ornt[0], r);
4081:         PetscInt edgeA = GetQuadEdge_Static(ornt[0], r);
4082:         PetscInt edgeB = (edgeA+3)%4;
4083:         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]);
4084:         coneNew[0]         = fStartNew + (cone[0] - fStart)*4 + subfA;
4085:         orntNew[0]         = ornt[0];
4086:         coneNew[1]         = fStartNew + (cone[1] - fStart)*4 + subfA;
4087:         orntNew[1]         = ornt[0];
4088:         coneNew[(r+0)%4+2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[edgeA+2] - fMax)*2 + (fornt[edgeA] < 0 ? 1 : 0);
4089:         orntNew[(r+0)%4+2] = ornt[edgeA];
4090:         coneNew[(r+1)%4+2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd          - fMax)*2 + (c - cMax)*4 + edgeA;
4091:         orntNew[(r+1)%4+2] = 0;
4092:         coneNew[(r+2)%4+2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd          - fMax)*2 + (c - cMax)*4 + edgeB;
4093:         orntNew[(r+2)%4+2] = -2;
4094:         coneNew[(r+3)%4+2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[edgeB+2] - fMax)*2 + (fornt[edgeB] < 0 ? 0 : 1);
4095:         orntNew[(r+3)%4+2] = ornt[edgeB];
4096:         DMPlexSetCone(rdm, newp+r, coneNew);
4097:         DMPlexSetConeOrientation(rdm, newp+r, orntNew);
4098: #if 1
4099:         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);
4100:         for (p = 0; p < 2; ++p) {
4101:           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);
4102:         }
4103:         for (p = 2; p < 6; ++p) {
4104:           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);
4105:         }
4106: #endif
4107:       }
4108:     }
4109:     /* Interior split faces have 4 edges and the same cells as the parent */
4110:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
4111:     PetscMalloc1((4 + maxSupportSize*2), &supportRef);
4112:     for (f = fStart; f < fMax; ++f) {
4113:       for (r = 0; r < 4; ++r) {
4114:         /* TODO: This can come from GetFaces_Internal() */
4115:         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};
4116:         const PetscInt  newp = fStartNew + (f - fStart)*4 + r;
4117:         const PetscInt *cone, *ornt, *support;
4118:         PetscInt        coneNew[4], orntNew[4], coneSize, c, supportSize, s;

4120:         DMPlexGetCone(dm, f, &cone);
4121:         DMPlexGetConeOrientation(dm, f, &ornt);
4122:         coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
4123:         orntNew[(r+3)%4] = ornt[(r+3)%4];
4124:         coneNew[(r+0)%4] = eStartNew + (cone[r]       - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
4125:         orntNew[(r+0)%4] = ornt[r];
4126:         coneNew[(r+1)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
4127:         orntNew[(r+1)%4] = 0;
4128:         coneNew[(r+2)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + (r+3)%4;
4129:         orntNew[(r+2)%4] = -2;
4130:         DMPlexSetCone(rdm, newp, coneNew);
4131:         DMPlexSetConeOrientation(rdm, newp, orntNew);
4132: #if 1
4133:         if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4134:         for (p = 0; p < 4; ++p) {
4135:           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);
4136:         }
4137: #endif
4138:         DMPlexGetSupportSize(dm, f, &supportSize);
4139:         DMPlexGetSupport(dm, f, &support);
4140:         for (s = 0; s < supportSize; ++s) {
4141:           PetscInt subf;
4142:           DMPlexGetConeSize(dm, support[s], &coneSize);
4143:           DMPlexGetCone(dm, support[s], &cone);
4144:           DMPlexGetConeOrientation(dm, support[s], &ornt);
4145:           for (c = 0; c < coneSize; ++c) {
4146:             if (cone[c] == f) break;
4147:           }
4148:           subf = GetQuadSubfaceInverse_Static(ornt[c], r);
4149:           if (support[s] < cMax) {
4150:             supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+subf];
4151:           } else {
4152:             supportRef[s] = cStartNew + (cMax       - cStart)*8 + (support[s] - cMax)*4 + subf;
4153:           }
4154:         }
4155:         DMPlexSetSupport(rdm, newp, supportRef);
4156: #if 1
4157:         if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4158:         for (p = 0; p < supportSize; ++p) {
4159:           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);
4160:         }
4161: #endif
4162:       }
4163:     }
4164:     /* Interior faces have 4 edges and 2 cells */
4165:     for (c = cStart; c < cMax; ++c) {
4166:       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};
4167:       const PetscInt *cone, *ornt;
4168:       PetscInt        newp, coneNew[4], orntNew[4], supportNew[2];

4170:       DMPlexGetCone(dm, c, &cone);
4171:       DMPlexGetConeOrientation(dm, c, &ornt);
4172:       /* A-D face */
4173:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 0;
4174:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
4175:       orntNew[0] = 0;
4176:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
4177:       orntNew[1] = 0;
4178:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
4179:       orntNew[2] = -2;
4180:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
4181:       orntNew[3] = -2;
4182:       DMPlexSetCone(rdm, newp, coneNew);
4183:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4184: #if 1
4185:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4186:       for (p = 0; p < 4; ++p) {
4187:         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);
4188:       }
4189: #endif
4190:       /* C-D face */
4191:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 1;
4192:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
4193:       orntNew[0] = 0;
4194:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
4195:       orntNew[1] = 0;
4196:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
4197:       orntNew[2] = -2;
4198:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
4199:       orntNew[3] = -2;
4200:       DMPlexSetCone(rdm, newp, coneNew);
4201:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4202: #if 1
4203:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4204:       for (p = 0; p < 4; ++p) {
4205:         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);
4206:       }
4207: #endif
4208:       /* B-C face */
4209:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 2;
4210:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
4211:       orntNew[0] = -2;
4212:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
4213:       orntNew[1] = 0;
4214:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
4215:       orntNew[2] = 0;
4216:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
4217:       orntNew[3] = -2;
4218:       DMPlexSetCone(rdm, newp, coneNew);
4219:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4220: #if 1
4221:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4222:       for (p = 0; p < 4; ++p) {
4223:         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);
4224:       }
4225: #endif
4226:       /* A-B face */
4227:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 3;
4228:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
4229:       orntNew[0] = -2;
4230:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
4231:       orntNew[1] = 0;
4232:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
4233:       orntNew[2] = 0;
4234:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
4235:       orntNew[3] = -2;
4236:       DMPlexSetCone(rdm, newp, coneNew);
4237:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4238: #if 1
4239:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4240:       for (p = 0; p < 4; ++p) {
4241:         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);
4242:       }
4243: #endif
4244:       /* E-F face */
4245:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 4;
4246:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
4247:       orntNew[0] = -2;
4248:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
4249:       orntNew[1] = -2;
4250:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
4251:       orntNew[2] = 0;
4252:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
4253:       orntNew[3] = 0;
4254:       DMPlexSetCone(rdm, newp, coneNew);
4255:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4256: #if 1
4257:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4258:       for (p = 0; p < 4; ++p) {
4259:         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);
4260:       }
4261: #endif
4262:       /* F-G face */
4263:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 5;
4264:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
4265:       orntNew[0] = -2;
4266:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
4267:       orntNew[1] = -2;
4268:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
4269:       orntNew[2] = 0;
4270:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
4271:       orntNew[3] = 0;
4272:       DMPlexSetCone(rdm, newp, coneNew);
4273:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4274: #if 1
4275:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4276:       for (p = 0; p < 4; ++p) {
4277:         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);
4278:       }
4279: #endif
4280:       /* G-H face */
4281:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 6;
4282:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
4283:       orntNew[0] = -2;
4284:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
4285:       orntNew[1] = 0;
4286:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
4287:       orntNew[2] = 0;
4288:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
4289:       orntNew[3] = -2;
4290:       DMPlexSetCone(rdm, newp, coneNew);
4291:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4292: #if 1
4293:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4294:       for (p = 0; p < 4; ++p) {
4295:         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);
4296:       }
4297: #endif
4298:       /* E-H face */
4299:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 7;
4300:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
4301:       orntNew[0] = -2;
4302:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
4303:       orntNew[1] = -2;
4304:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
4305:       orntNew[2] = 0;
4306:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
4307:       orntNew[3] = 0;
4308:       DMPlexSetCone(rdm, newp, coneNew);
4309:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4310: #if 1
4311:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4312:       for (p = 0; p < 4; ++p) {
4313:         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);
4314:       }
4315: #endif
4316:       /* A-E face */
4317:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 8;
4318:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
4319:       orntNew[0] = 0;
4320:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
4321:       orntNew[1] = 0;
4322:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
4323:       orntNew[2] = -2;
4324:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
4325:       orntNew[3] = -2;
4326:       DMPlexSetCone(rdm, newp, coneNew);
4327:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4328: #if 1
4329:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4330:       for (p = 0; p < 4; ++p) {
4331:         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);
4332:       }
4333: #endif
4334:       /* D-F face */
4335:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 9;
4336:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
4337:       orntNew[0] = -2;
4338:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
4339:       orntNew[1] = 0;
4340:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
4341:       orntNew[2] = 0;
4342:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
4343:       orntNew[3] = -2;
4344:       DMPlexSetCone(rdm, newp, coneNew);
4345:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4346: #if 1
4347:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4348:       for (p = 0; p < 4; ++p) {
4349:         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);
4350:       }
4351: #endif
4352:       /* C-G face */
4353:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 10;
4354:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
4355:       orntNew[0] = -2;
4356:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
4357:       orntNew[1] = -2;
4358:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
4359:       orntNew[2] = 0;
4360:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
4361:       orntNew[3] = 0;
4362:       DMPlexSetCone(rdm, newp, coneNew);
4363:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4364: #if 1
4365:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4366:       for (p = 0; p < 4; ++p) {
4367:         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);
4368:       }
4369: #endif
4370:       /* B-H face */
4371:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 11;
4372:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
4373:       orntNew[0] = 0;
4374:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
4375:       orntNew[1] = -2;
4376:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
4377:       orntNew[2] = -2;
4378:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
4379:       orntNew[3] = 0;
4380:       DMPlexSetCone(rdm, newp, coneNew);
4381:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4382: #if 1
4383:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4384:       for (p = 0; p < 4; ++p) {
4385:         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);
4386:       }
4387: #endif
4388:       for (r = 0; r < 12; ++r) {
4389:         newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + r;
4390:         supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
4391:         supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
4392:         DMPlexSetSupport(rdm, newp, supportNew);
4393: #if 1
4394:         if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4395:         for (p = 0; p < 2; ++p) {
4396:           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);
4397:         }
4398: #endif
4399:       }
4400:     }
4401:     /* Hybrid split faces have 4 edges and same cells */
4402:     for (f = fMax; f < fEnd; ++f) {
4403:       const PetscInt *cone, *ornt, *support;
4404:       PetscInt        coneNew[4], orntNew[4];
4405:       PetscInt        supportNew[2], size, s, c;

4407:       DMPlexGetCone(dm, f, &cone);
4408:       DMPlexGetConeOrientation(dm, f, &ornt);
4409:       DMPlexGetSupportSize(dm, f, &size);
4410:       DMPlexGetSupport(dm, f, &support);
4411:       for (r = 0; r < 2; ++r) {
4412:         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + r;

4414:         coneNew[0]   = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
4415:         orntNew[0]   = ornt[0];
4416:         coneNew[1]   = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
4417:         orntNew[1]   = ornt[1];
4418:         coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (cone[2+r] - eMax);
4419:         orntNew[2+r] = 0;
4420:         coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd      - eMax) + (f - fMax);
4421:         orntNew[3-r] = 0;
4422:         DMPlexSetCone(rdm, newp, coneNew);
4423:         DMPlexSetConeOrientation(rdm, newp, orntNew);
4424: #if 1
4425:         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
4426:         for (p = 0; p < 2; ++p) {
4427:           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);
4428:         }
4429:         for (p = 2; p < 4; ++p) {
4430:           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);
4431:         }
4432: #endif
4433:         for (s = 0; s < size; ++s) {
4434:           const PetscInt *coneCell, *orntCell, *fornt;

4436:           DMPlexGetCone(dm, support[s], &coneCell);
4437:           DMPlexGetConeOrientation(dm, support[s], &orntCell);
4438:           for (c = 2; c < 6; ++c) if (coneCell[c] == f) break;
4439:           if (c >= 6) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of cell %d", f, support[s]);
4440:           DMPlexGetConeOrientation(dm, coneCell[0], &fornt);
4441:           supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetQuadEdgeInverse_Static(orntCell[0], c-2) + (fornt[c-2] < 0 ? 1-r : r))%4;
4442:         }
4443:         DMPlexSetSupport(rdm, newp, supportNew);
4444: #if 1
4445:         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
4446:         for (p = 0; p < size; ++p) {
4447:           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);
4448:         }
4449: #endif
4450:       }
4451:     }
4452:     /* Hybrid cell faces have 4 edges and 2 cells */
4453:     for (c = cMax; c < cEnd; ++c) {
4454:       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4;
4455:       const PetscInt *cone, *ornt;
4456:       PetscInt        coneNew[4], orntNew[4];
4457:       PetscInt        supportNew[2];

4459:       DMPlexGetCone(dm, c, &cone);
4460:       DMPlexGetConeOrientation(dm, c, &ornt);
4461:       for (r = 0; r < 4; ++r) {
4462:         coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], r);
4463:         orntNew[0] = 0;
4464:         coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], r);
4465:         orntNew[1] = 0;
4466:         coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (cone[2+GetQuadEdge_Static(ornt[0], r)] - fMax);
4467:         orntNew[2] = 0;
4468:         coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd                                   - fMax) + (c - cMax);
4469:         orntNew[3] = 0;
4470:         DMPlexSetCone(rdm, newp+r, coneNew);
4471:         DMPlexSetConeOrientation(rdm, newp+r, orntNew);
4472: #if 1
4473:         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);
4474:         for (p = 0; p < 2; ++p) {
4475:           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);
4476:         }
4477:         for (p = 2; p < 4; ++p) {
4478:           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);
4479:         }
4480: #endif
4481:         supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], r);
4482:         supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], (r+1)%4);
4483:         DMPlexSetSupport(rdm, newp+r, supportNew);
4484: #if 1
4485:         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);
4486:         for (p = 0; p < 2; ++p) {
4487:           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);
4488:         }
4489: #endif
4490:       }
4491:     }
4492:     /* Interior split edges have 2 vertices and the same faces as the parent */
4493:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
4494:     for (e = eStart; e < eMax; ++e) {
4495:       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);

4497:       for (r = 0; r < 2; ++r) {
4498:         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
4499:         const PetscInt *cone, *ornt, *support;
4500:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

4502:         DMPlexGetCone(dm, e, &cone);
4503:         coneNew[0]       = vStartNew + (cone[0] - vStart);
4504:         coneNew[1]       = vStartNew + (cone[1] - vStart);
4505:         coneNew[(r+1)%2] = newv;
4506:         DMPlexSetCone(rdm, newp, coneNew);
4507: #if 1
4508:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4509:         for (p = 0; p < 2; ++p) {
4510:           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);
4511:         }
4512: #endif
4513:         DMPlexGetSupportSize(dm, e, &supportSize);
4514:         DMPlexGetSupport(dm, e, &support);
4515:         for (s = 0; s < supportSize; ++s) {
4516:           DMPlexGetConeSize(dm, support[s], &coneSize);
4517:           DMPlexGetCone(dm, support[s], &cone);
4518:           DMPlexGetConeOrientation(dm, support[s], &ornt);
4519:           for (c = 0; c < coneSize; ++c) {
4520:             if (cone[c] == e) break;
4521:           }
4522:           if (support[s] < fMax) {
4523:             supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%4;
4524:           } else {
4525:             supportRef[s] = fStartNew + (fMax       - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
4526:           }
4527:         }
4528:         DMPlexSetSupport(rdm, newp, supportRef);
4529: #if 1
4530:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4531:         for (p = 0; p < supportSize; ++p) {
4532:           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);
4533:         }
4534: #endif
4535:       }
4536:     }
4537:     /* Interior face edges have 2 vertices and 2+cells faces */
4538:     for (f = fStart; f < fMax; ++f) {
4539:       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};
4540:       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
4541:       const PetscInt *cone, *coneCell, *orntCell, *support;
4542:       PetscInt        coneNew[2], coneSize, c, supportSize, s;

4544:       DMPlexGetCone(dm, f, &cone);
4545:       for (r = 0; r < 4; ++r) {
4546:         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;

4548:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
4549:         coneNew[1] = newv;
4550:         DMPlexSetCone(rdm, newp, coneNew);
4551: #if 1
4552:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4553:         for (p = 0; p < 2; ++p) {
4554:           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);
4555:         }
4556: #endif
4557:         DMPlexGetSupportSize(dm, f, &supportSize);
4558:         DMPlexGetSupport(dm, f, &support);
4559:         supportRef[0] = fStartNew + (f - fStart)*4 + r;
4560:         supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
4561:         for (s = 0; s < supportSize; ++s) {
4562:           DMPlexGetConeSize(dm, support[s], &coneSize);
4563:           DMPlexGetCone(dm, support[s], &coneCell);
4564:           DMPlexGetConeOrientation(dm, support[s], &orntCell);
4565:           for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
4566:           if (support[s] < cMax) {
4567:             supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
4568:           } else {
4569:             supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + GetQuadEdgeInverse_Static(orntCell[c], r);
4570:           }
4571:         }
4572:         DMPlexSetSupport(rdm, newp, supportRef);
4573: #if 1
4574:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4575:         for (p = 0; p < 2+supportSize; ++p) {
4576:           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);
4577:         }
4578: #endif
4579:       }
4580:     }
4581:     /* Interior cell edges have 2 vertices and 4 faces */
4582:     for (c = cStart; c < cMax; ++c) {
4583:       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};
4584:       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
4585:       const PetscInt *cone;
4586:       PetscInt        coneNew[2], supportNew[4];

4588:       DMPlexGetCone(dm, c, &cone);
4589:       for (r = 0; r < 6; ++r) {
4590:         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;

4592:         coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[r] - fStart);
4593:         coneNew[1] = newv;
4594:         DMPlexSetCone(rdm, newp, coneNew);
4595: #if 1
4596:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4597:         for (p = 0; p < 2; ++p) {
4598:           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);
4599:         }
4600: #endif
4601:         for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
4602:         DMPlexSetSupport(rdm, newp, supportNew);
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 < 4; ++p) {
4606:           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);
4607:         }
4608: #endif
4609:       }
4610:     }
4611:     /* Hybrid edges have two vertices and the same faces */
4612:     for (e = eMax; e < eEnd; ++e) {
4613:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (e - eMax);
4614:       const PetscInt *cone, *support, *fcone;
4615:       PetscInt        coneNew[2], size, fsize, s;

4617:       DMPlexGetCone(dm, e, &cone);
4618:       DMPlexGetSupportSize(dm, e, &size);
4619:       DMPlexGetSupport(dm, e, &support);
4620:       coneNew[0] = vStartNew + (cone[0] - vStart);
4621:       coneNew[1] = vStartNew + (cone[1] - vStart);
4622:       DMPlexSetCone(rdm, newp, coneNew);
4623: #if 1
4624:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4625:       for (p = 0; p < 2; ++p) {
4626:         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);
4627:       }
4628: #endif
4629:       for (s = 0; s < size; ++s) {
4630:         DMPlexGetConeSize(dm, support[s], &fsize);
4631:         DMPlexGetCone(dm, support[s], &fcone);
4632:         for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
4633:         if ((c < 2) || (c > 3)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge %d not found in cone of face %d", e, support[s]);
4634:         supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + c-2;
4635:       }
4636:       DMPlexSetSupport(rdm, newp, supportRef);
4637: #if 1
4638:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4639:       for (p = 0; p < size; ++p) {
4640:         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);
4641:       }
4642: #endif
4643:     }
4644:     /* Hybrid face edges have 2 vertices and 2+cells faces */
4645:     for (f = fMax; f < fEnd; ++f) {
4646:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
4647:       const PetscInt *cone, *support, *ccone, *cornt;
4648:       PetscInt        coneNew[2], size, csize, s;

4650:       DMPlexGetCone(dm, f, &cone);
4651:       DMPlexGetSupportSize(dm, f, &size);
4652:       DMPlexGetSupport(dm, f, &support);
4653:       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
4654:       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
4655:       DMPlexSetCone(rdm, newp, coneNew);
4656: #if 1
4657:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4658:       for (p = 0; p < 2; ++p) {
4659:         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);
4660:       }
4661: #endif
4662:       supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 0;
4663:       supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 1;
4664:       for (s = 0; s < size; ++s) {
4665:         DMPlexGetConeSize(dm, support[s], &csize);
4666:         DMPlexGetCone(dm, support[s], &ccone);
4667:         DMPlexGetConeOrientation(dm, support[s], &cornt);
4668:         for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
4669:         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]);
4670:         supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + GetQuadSubfaceInverse_Static(cornt[0], c-2);
4671:       }
4672:       DMPlexSetSupport(rdm, newp, supportRef);
4673: #if 1
4674:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4675:       for (p = 0; p < 2+size; ++p) {
4676:         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);
4677:       }
4678: #endif
4679:     }
4680:     /* Hybrid cell edges have 2 vertices and 4 faces */
4681:     for (c = cMax; c < cEnd; ++c) {
4682:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
4683:       const PetscInt *cone, *support;
4684:       PetscInt        coneNew[2], size;

4686:       DMPlexGetCone(dm, c, &cone);
4687:       DMPlexGetSupportSize(dm, c, &size);
4688:       DMPlexGetSupport(dm, c, &support);
4689:       coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[0] - fStart);
4690:       coneNew[1] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[1] - fStart);
4691:       DMPlexSetCone(rdm, newp, coneNew);
4692: #if 1
4693:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4694:       for (p = 0; p < 2; ++p) {
4695:         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);
4696:       }
4697: #endif
4698:       supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 0;
4699:       supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 1;
4700:       supportRef[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 2;
4701:       supportRef[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 3;
4702:       DMPlexSetSupport(rdm, newp, supportRef);
4703: #if 1
4704:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4705:       for (p = 0; p < 4; ++p) {
4706:         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);
4707:       }
4708: #endif
4709:     }
4710:     /* Interior vertices have identical supports */
4711:     for (v = vStart; v < vEnd; ++v) {
4712:       const PetscInt  newp = vStartNew + (v - vStart);
4713:       const PetscInt *support, *cone;
4714:       PetscInt        size, s;

4716:       DMPlexGetSupportSize(dm, v, &size);
4717:       DMPlexGetSupport(dm, v, &support);
4718:       for (s = 0; s < size; ++s) {
4719:         PetscInt r = 0;

4721:         DMPlexGetCone(dm, support[s], &cone);
4722:         if (cone[1] == v) r = 1;
4723:         if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
4724:         else                   supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (support[s] - eMax);
4725:       }
4726:       DMPlexSetSupport(rdm, newp, supportRef);
4727: #if 1
4728:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4729:       for (p = 0; p < size; ++p) {
4730:         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);
4731:       }
4732: #endif
4733:     }
4734:     /* Interior edge vertices have 2 + faces supports */
4735:     for (e = eStart; e < eMax; ++e) {
4736:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
4737:       const PetscInt *cone, *support;
4738:       PetscInt        size, s;

4740:       DMPlexGetSupportSize(dm, e, &size);
4741:       DMPlexGetSupport(dm, e, &support);
4742:       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
4743:       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
4744:       for (s = 0; s < size; ++s) {
4745:         PetscInt r;

4747:         DMPlexGetCone(dm, support[s], &cone);
4748:         for (r = 0; r < 4; ++r) if (cone[r] == e) break;
4749:         if (support[s] < fMax) {
4750:           supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*4 + r;
4751:         } else {
4752:           supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (fMax       - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (support[s] - fMax);
4753:         }
4754:       }
4755:       DMPlexSetSupport(rdm, newp, supportRef);
4756: #if 1
4757:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4758:       for (p = 0; p < 2+size; ++p) {
4759:         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);
4760:       }
4761: #endif
4762:     }
4763:     /* Interior face vertices have 4 + cells supports */
4764:     for (f = fStart; f < fMax; ++f) {
4765:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
4766:       const PetscInt *cone, *support;
4767:       PetscInt        size, s;

4769:       DMPlexGetSupportSize(dm, f, &size);
4770:       DMPlexGetSupport(dm, f, &support);
4771:       for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eMax - eStart)*2 +  (f - fStart)*4 + r;
4772:       for (s = 0; s < size; ++s) {
4773:         PetscInt r;

4775:         DMPlexGetCone(dm, support[s], &cone);
4776:         for (r = 0; r < 6; ++r) if (cone[r] == f) break;
4777:         if (support[s] < cMax) {
4778:           supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (support[s] - cStart)*6 + r;
4779:         } else {
4780:           supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax       - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (support[s] - cMax);
4781:         }
4782:       }
4783:       DMPlexSetSupport(rdm, newp, supportRef);
4784: #if 1
4785:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4786:       for (p = 0; p < 4+size; ++p) {
4787:         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);
4788:       }
4789: #endif
4790:     }
4791:     /* Cell vertices have 6 supports */
4792:     for (c = cStart; c < cMax; ++c) {
4793:       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
4794:       PetscInt       supportNew[6];

4796:       for (r = 0; r < 6; ++r) {
4797:         supportNew[r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
4798:       }
4799:       DMPlexSetSupport(rdm, newp, supportNew);
4800:     }
4801:     PetscFree(supportRef);
4802:     break;
4803:   default:
4804:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
4805:   }
4806:   return(0);
4807: }

4811: static PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
4812: {
4813:   PetscSection   coordSection, coordSectionNew;
4814:   Vec            coordinates, coordinatesNew;
4815:   PetscScalar   *coords, *coordsNew;
4816:   const PetscInt numVertices = depthSize ? depthSize[0] : 0;
4817:   PetscInt       dim, depth, coordSizeNew, cStart, cEnd, cMax, c, vStart, vStartNew, vEnd, v, eStart, eEnd, eMax, e, fStart, fEnd, fMax, f;

4821:   DMPlexGetDimension(dm, &dim);
4822:   DMPlexGetDepth(dm, &depth);
4823:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
4824:   DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
4825:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
4826:   DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
4827:   DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, NULL);
4828:   if (refiner) {GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);}
4829:   GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);
4830:   DMGetCoordinateSection(dm, &coordSection);
4831:   PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);
4832:   PetscSectionSetNumFields(coordSectionNew, 1);
4833:   PetscSectionSetFieldComponents(coordSectionNew, 0, dim);
4834:   PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+numVertices);
4835:   if (cMax < 0) cMax = cEnd;
4836:   if (fMax < 0) fMax = fEnd;
4837:   if (eMax < 0) eMax = eEnd;
4838:   /* All vertices have the dim coordinates */
4839:   for (v = vStartNew; v < vStartNew+numVertices; ++v) {
4840:     PetscSectionSetDof(coordSectionNew, v, dim);
4841:     PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);
4842:   }
4843:   PetscSectionSetUp(coordSectionNew);
4844:   DMSetCoordinateSection(rdm, coordSectionNew);
4845:   DMGetCoordinatesLocal(dm, &coordinates);
4846:   PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);
4847:   VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);
4848:   PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");
4849:   VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);
4850:   VecSetFromOptions(coordinatesNew);
4851:   VecGetArray(coordinates, &coords);
4852:   VecGetArray(coordinatesNew, &coordsNew);
4853:   switch (refiner) {
4854:   case 0: break;
4855:   case 6: /* Hex 3D */
4856:   case 8: /* Hybrid Hex 3D */
4857:     /* Face vertices have the average of corner coordinates */
4858:     for (f = fStart; f < fMax; ++f) {
4859:       const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
4860:       PetscInt      *cone = NULL;
4861:       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;

4863:       DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);
4864:       for (p = 0; p < closureSize*2; p += 2) {
4865:         const PetscInt point = cone[p];
4866:         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
4867:       }
4868:       for (v = 0; v < coneSize; ++v) {
4869:         PetscSectionGetOffset(coordSection, cone[v], &off[v]);
4870:       }
4871:       PetscSectionGetOffset(coordSectionNew, newv, &offnew);
4872:       for (d = 0; d < dim; ++d) {
4873:         coordsNew[offnew+d] = 0.0;
4874:         for (v = 0; v < coneSize; ++v) coordsNew[offnew+d] += coords[off[v]+d];
4875:         coordsNew[offnew+d] /= coneSize;
4876:       }
4877:       DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);
4878:     }
4879:   case 2: /* Hex 2D */
4880:     /* Cell vertices have the average of corner coordinates */
4881:     for (c = cStart; c < cMax; ++c) {
4882:       const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (c - cStart) + (dim > 2 ? (fMax - fStart) : 0);
4883:       PetscInt      *cone = NULL;
4884:       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;

4886:       DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);
4887:       for (p = 0; p < closureSize*2; p += 2) {
4888:         const PetscInt point = cone[p];
4889:         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
4890:       }
4891:       for (v = 0; v < coneSize; ++v) {
4892:         PetscSectionGetOffset(coordSection, cone[v], &off[v]);
4893:       }
4894:       PetscSectionGetOffset(coordSectionNew, newv, &offnew);
4895:       for (d = 0; d < dim; ++d) {
4896:         coordsNew[offnew+d] = 0.0;
4897:         for (v = 0; v < coneSize; ++v) coordsNew[offnew+d] += coords[off[v]+d];
4898:         coordsNew[offnew+d] /= coneSize;
4899:       }
4900:       DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);
4901:     }
4902:   case 1: /* Simplicial 2D */
4903:   case 3: /* Hybrid Simplicial 2D */
4904:   case 5: /* Simplicial 3D */
4905:   case 7: /* Hybrid Simplicial 3D */
4906:     /* Edge vertices have the average of endpoint coordinates */
4907:     for (e = eStart; e < eMax; ++e) {
4908:       const PetscInt  newv = vStartNew + (vEnd - vStart) + (e - eStart);
4909:       const PetscInt *cone;
4910:       PetscInt        coneSize, offA, offB, offnew, d;

4912:       DMPlexGetConeSize(dm, e, &coneSize);
4913:       if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize);
4914:       DMPlexGetCone(dm, e, &cone);
4915:       PetscSectionGetOffset(coordSection, cone[0], &offA);
4916:       PetscSectionGetOffset(coordSection, cone[1], &offB);
4917:       PetscSectionGetOffset(coordSectionNew, newv, &offnew);
4918:       for (d = 0; d < dim; ++d) {
4919:         coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]);
4920:       }
4921:     }
4922:     /* Old vertices have the same coordinates */
4923:     for (v = vStart; v < vEnd; ++v) {
4924:       const PetscInt newv = vStartNew + (v - vStart);
4925:       PetscInt       off, offnew, d;

4927:       PetscSectionGetOffset(coordSection, v, &off);
4928:       PetscSectionGetOffset(coordSectionNew, newv, &offnew);
4929:       for (d = 0; d < dim; ++d) {
4930:         coordsNew[offnew+d] = coords[off+d];
4931:       }
4932:     }
4933:     break;
4934:   default:
4935:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
4936:   }
4937:   VecRestoreArray(coordinates, &coords);
4938:   VecRestoreArray(coordinatesNew, &coordsNew);
4939:   DMSetCoordinatesLocal(rdm, coordinatesNew);
4940:   VecDestroy(&coordinatesNew);
4941:   PetscSectionDestroy(&coordSectionNew);
4942:   return(0);
4943: }

4947: static PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
4948: {
4949:   PetscInt           numRoots, numLeaves, l;
4950:   const PetscInt    *localPoints;
4951:   const PetscSFNode *remotePoints;
4952:   PetscInt          *localPointsNew;
4953:   PetscSFNode       *remotePointsNew;
4954:   PetscInt          *ranks, *ranksNew;
4955:   PetscErrorCode     ierr;

4958:   PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);
4959:   PetscMalloc1(numLeaves, &ranks);
4960:   for (l = 0; l < numLeaves; ++l) {
4961:     ranks[l] = remotePoints[l].rank;
4962:   }
4963:   PetscSortRemoveDupsInt(&numLeaves, ranks);
4964:   PetscMalloc1(numLeaves,    &ranksNew);
4965:   PetscMalloc1(numLeaves,    &localPointsNew);
4966:   PetscMalloc1(numLeaves, &remotePointsNew);
4967:   for (l = 0; l < numLeaves; ++l) {
4968:     ranksNew[l]              = ranks[l];
4969:     localPointsNew[l]        = l;
4970:     remotePointsNew[l].index = 0;
4971:     remotePointsNew[l].rank  = ranksNew[l];
4972:   }
4973:   PetscFree(ranks);
4974:   ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);
4975:   PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);
4976:   PetscSFSetFromOptions(*sfProcess);
4977:   PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);
4978:   return(0);
4979: }

4983: static PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
4984: {
4985:   PetscSF            sf, sfNew, sfProcess;
4986:   IS                 processRanks;
4987:   MPI_Datatype       depthType;
4988:   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
4989:   const PetscInt    *localPoints, *neighbors;
4990:   const PetscSFNode *remotePoints;
4991:   PetscInt          *localPointsNew;
4992:   PetscSFNode       *remotePointsNew;
4993:   PetscInt          *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
4994:   PetscInt           depth, numNeighbors, pStartNew, pEndNew, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r, n;
4995:   PetscInt           cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
4996:   PetscErrorCode     ierr;

4999:   DMPlexGetChart(rdm, &pStartNew, &pEndNew);
5000:   DMPlexGetDepth(dm, &depth);
5001:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
5002:   DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
5003:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
5004:   DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
5005:   DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
5006:   if (refiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
5007:   DMGetPointSF(dm, &sf);
5008:   DMGetPointSF(rdm, &sfNew);
5009:   /* Caculate size of new SF */
5010:   PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);
5011:   if (numRoots < 0) return(0);
5012:   for (l = 0; l < numLeaves; ++l) {
5013:     const PetscInt p = localPoints[l];

5015:     switch (refiner) {
5016:     case 1:
5017:       /* Simplicial 2D */
5018:       if ((p >= vStart) && (p < vEnd)) {
5019:         /* Old vertices stay the same */
5020:         ++numLeavesNew;
5021:       } else if ((p >= fStart) && (p < fEnd)) {
5022:         /* Old faces add new faces and vertex */
5023:         numLeavesNew += 2 + 1;
5024:       } else if ((p >= cStart) && (p < cEnd)) {
5025:         /* Old cells add new cells and interior faces */
5026:         numLeavesNew += 4 + 3;
5027:       }
5028:       break;
5029:     case 2:
5030:       /* Hex 2D */
5031:       if ((p >= vStart) && (p < vEnd)) {
5032:         /* Old vertices stay the same */
5033:         ++numLeavesNew;
5034:       } else if ((p >= fStart) && (p < fEnd)) {
5035:         /* Old faces add new faces and vertex */
5036:         numLeavesNew += 2 + 1;
5037:       } else if ((p >= cStart) && (p < cEnd)) {
5038:         /* Old cells add new cells, interior faces, and vertex */
5039:         numLeavesNew += 4 + 4 + 1;
5040:       }
5041:       break;
5042:     case 5:
5043:       /* Simplicial 3D */
5044:       if ((p >= vStart) && (p < vEnd)) {
5045:         /* Old vertices stay the same */
5046:         ++numLeavesNew;
5047:       } else if ((p >= eStart) && (p < eEnd)) {
5048:         /* Old edges add new edges and vertex */
5049:         numLeavesNew += 2 + 1;
5050:       } else if ((p >= fStart) && (p < fEnd)) {
5051:         /* Old faces add new faces and face edges */
5052:         numLeavesNew += 4 + 3;
5053:       } else if ((p >= cStart) && (p < cEnd)) {
5054:         /* Old cells add new cells and interior faces and edges */
5055:         numLeavesNew += 8 + 8 + 1;
5056:       }
5057:       break;
5058:     case 7:
5059:       /* Hybrid Simplicial 3D */
5060:       if ((p >= vStart) && (p < vEnd)) {
5061:         /* Interior vertices stay the same */
5062:         ++numLeavesNew;
5063:       } else if ((p >= eStart) && (p < eMax)) {
5064:         /* Interior edges add new edges and vertex */
5065:         numLeavesNew += 2 + 1;
5066:       } else if ((p >= eMax) && (p < eEnd)) {
5067:         /* Hybrid edges stay the same */
5068:         ++numLeavesNew;
5069:       } else if ((p >= fStart) && (p < fMax)) {
5070:         /* Interior faces add new faces and edges */
5071:         numLeavesNew += 4 + 3;
5072:       } else if ((p >= fMax) && (p < fEnd)) {
5073:         /* Hybrid faces add new faces and edges */
5074:         numLeavesNew += 2 + 1;
5075:       } else if ((p >= cStart) && (p < cMax)) {
5076:         /* Interior cells add new cells, faces, and edges */
5077:         numLeavesNew += 8 + 8 + 1;
5078:       } else if ((p >= cMax) && (p < cEnd)) {
5079:         /* Hybrid cells add new cells and faces */
5080:         numLeavesNew += 4 + 3;
5081:       }
5082:       break;
5083:     case 6:
5084:       /* Hex 3D */
5085:       if ((p >= vStart) && (p < vEnd)) {
5086:         /* Old vertices stay the same */
5087:         ++numLeavesNew;
5088:       } else if ((p >= eStart) && (p < eEnd)) {
5089:         /* Old edges add new edges, and vertex */
5090:         numLeavesNew += 2 + 1;
5091:       } else if ((p >= fStart) && (p < fEnd)) {
5092:         /* Old faces add new faces, edges, and vertex */
5093:         numLeavesNew += 4 + 4 + 1;
5094:       } else if ((p >= cStart) && (p < cEnd)) {
5095:         /* Old cells add new cells, faces, edges, and vertex */
5096:         numLeavesNew += 8 + 12 + 6 + 1;
5097:       }
5098:       break;
5099:     case 8:
5100:       /* Hybrid Hex 3D */
5101:       if ((p >= vStart) && (p < vEnd)) {
5102:         /* Old vertices stay the same */
5103:         ++numLeavesNew;
5104:       } else if ((p >= eStart) && (p < eMax)) {
5105:         /* Interior edges add new edges, and vertex */
5106:         numLeavesNew += 2 + 1;
5107:       } else if ((p >= eMax) && (p < eEnd)) {
5108:         /* Hybrid edges stay the same */
5109:         ++numLeavesNew;
5110:       } else if ((p >= fStart) && (p < fMax)) {
5111:         /* Interior faces add new faces, edges, and vertex */
5112:         numLeavesNew += 4 + 4 + 1;
5113:       } else if ((p >= fMax) && (p < fEnd)) {
5114:         /* Hybrid faces add new faces and edges */
5115:         numLeavesNew += 2 + 1;
5116:       } else if ((p >= cStart) && (p < cMax)) {
5117:         /* Interior cells add new cells, faces, edges, and vertex */
5118:         numLeavesNew += 8 + 12 + 6 + 1;
5119:       } else if ((p >= cStart) && (p < cEnd)) {
5120:         /* Hybrid cells add new cells, faces, and edges */
5121:         numLeavesNew += 4 + 4 + 1;
5122:       }
5123:       break;
5124:     default:
5125:       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5126:     }
5127:   }
5128:   /* Communicate depthSizes for each remote rank */
5129:   DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);
5130:   ISGetLocalSize(processRanks, &numNeighbors);
5131:   PetscMalloc5((depth+1)*numNeighbors,&rdepthSize,numNeighbors,&rvStartNew,numNeighbors,&reStartNew,numNeighbors,&rfStartNew,numNeighbors,&rcStartNew);
5132:   PetscMalloc7(depth+1,&depthSizeOld,(depth+1)*numNeighbors,&rdepthSizeOld,(depth+1)*numNeighbors,&rdepthMaxOld,numNeighbors,&rvStart,numNeighbors,&reStart,numNeighbors,&rfStart,numNeighbors,&rcStart);
5133:   MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);
5134:   MPI_Type_commit(&depthType);
5135:   PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);
5136:   PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);
5137:   for (n = 0; n < numNeighbors; ++n) {
5138:     GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);
5139:   }
5140:   depthSizeOld[depth]   = cMax;
5141:   depthSizeOld[0]       = vMax;
5142:   depthSizeOld[depth-1] = fMax;
5143:   depthSizeOld[1]       = eMax;

5145:   PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);
5146:   PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);

5148:   depthSizeOld[depth]   = cEnd - cStart;
5149:   depthSizeOld[0]       = vEnd - vStart;
5150:   depthSizeOld[depth-1] = fEnd - fStart;
5151:   depthSizeOld[1]       = eEnd - eStart;

5153:   PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);
5154:   PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);
5155:   for (n = 0; n < numNeighbors; ++n) {
5156:     GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);
5157:   }
5158:   MPI_Type_free(&depthType);
5159:   PetscSFDestroy(&sfProcess);
5160:   /* Calculate new point SF */
5161:   PetscMalloc1(numLeavesNew,    &localPointsNew);
5162:   PetscMalloc1(numLeavesNew, &remotePointsNew);
5163:   ISGetIndices(processRanks, &neighbors);
5164:   for (l = 0, m = 0; l < numLeaves; ++l) {
5165:     PetscInt    p     = localPoints[l];
5166:     PetscInt    rp    = remotePoints[l].index, n;
5167:     PetscMPIInt rrank = remotePoints[l].rank;

5169:     PetscFindInt(rrank, numNeighbors, neighbors, &n);
5170:     if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank);
5171:     switch (refiner) {
5172:     case 1:
5173:       /* Simplicial 2D */
5174:       if ((p >= vStart) && (p < vEnd)) {
5175:         /* Old vertices stay the same */
5176:         localPointsNew[m]        = vStartNew     + (p  - vStart);
5177:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5178:         remotePointsNew[m].rank  = rrank;
5179:         ++m;
5180:       } else if ((p >= fStart) && (p < fEnd)) {
5181:         /* Old faces add new faces and vertex */
5182:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
5183:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
5184:         remotePointsNew[m].rank  = rrank;
5185:         ++m;
5186:         for (r = 0; r < 2; ++r, ++m) {
5187:           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
5188:           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
5189:           remotePointsNew[m].rank  = rrank;
5190:         }
5191:       } else if ((p >= cStart) && (p < cEnd)) {
5192:         /* Old cells add new cells and interior faces */
5193:         for (r = 0; r < 4; ++r, ++m) {
5194:           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
5195:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5196:           remotePointsNew[m].rank  = rrank;
5197:         }
5198:         for (r = 0; r < 3; ++r, ++m) {
5199:           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*3     + r;
5200:           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r;
5201:           remotePointsNew[m].rank  = rrank;
5202:         }
5203:       }
5204:       break;
5205:     case 2:
5206:       /* Hex 2D */
5207:       if ((p >= vStart) && (p < vEnd)) {
5208:         /* Old vertices stay the same */
5209:         localPointsNew[m]        = vStartNew     + (p  - vStart);
5210:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5211:         remotePointsNew[m].rank  = rrank;
5212:         ++m;
5213:       } else if ((p >= fStart) && (p < fEnd)) {
5214:         /* Old faces add new faces and vertex */
5215:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
5216:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
5217:         remotePointsNew[m].rank  = rrank;
5218:         ++m;
5219:         for (r = 0; r < 2; ++r, ++m) {
5220:           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
5221:           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
5222:           remotePointsNew[m].rank  = rrank;
5223:         }
5224:       } else if ((p >= cStart) && (p < cEnd)) {
5225:         /* Old cells add new cells, interior faces, and vertex */
5226:         for (r = 0; r < 4; ++r, ++m) {
5227:           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
5228:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5229:           remotePointsNew[m].rank  = rrank;
5230:         }
5231:         for (r = 0; r < 4; ++r, ++m) {
5232:           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*4     + r;
5233:           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r;
5234:           remotePointsNew[m].rank  = rrank;
5235:         }
5236:         for (r = 0; r < 1; ++r, ++m) {
5237:           localPointsNew[m]        = vStartNew     + (fEnd - fStart)                    + (p  - cStart)     + r;
5238:           remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]) + r;
5239:           remotePointsNew[m].rank  = rrank;
5240:         }
5241:       }
5242:       break;
5243:     case 3:
5244:       /* Hybrid simplicial 2D */
5245:       if ((p >= vStart) && (p < vEnd)) {
5246:         /* Old vertices stay the same */
5247:         localPointsNew[m]        = vStartNew     + (p  - vStart);
5248:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5249:         remotePointsNew[m].rank  = rrank;
5250:         ++m;
5251:       } else if ((p >= fStart) && (p < fMax)) {
5252:         /* Old interior faces add new faces and vertex */
5253:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
5254:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
5255:         remotePointsNew[m].rank  = rrank;
5256:         ++m;
5257:         for (r = 0; r < 2; ++r, ++m) {
5258:           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
5259:           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
5260:           remotePointsNew[m].rank  = rrank;
5261:         }
5262:       } else if ((p >= fMax) && (p < fEnd)) {
5263:         /* Old hybrid faces stay the same */
5264:         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - fMax);
5265:         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
5266:         remotePointsNew[m].rank  = rrank;
5267:         ++m;
5268:       } else if ((p >= cStart) && (p < cMax)) {
5269:         /* Old interior cells add new cells and interior faces */
5270:         for (r = 0; r < 4; ++r, ++m) {
5271:           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
5272:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5273:           remotePointsNew[m].rank  = rrank;
5274:         }
5275:         for (r = 0; r < 3; ++r, ++m) {
5276:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - cStart)*3     + r;
5277:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r;
5278:           remotePointsNew[m].rank  = rrank;
5279:         }
5280:       } else if ((p >= cStart) && (p < cMax)) {
5281:         /* Old hybrid cells add new cells and hybrid face */
5282:         for (r = 0; r < 2; ++r, ++m) {
5283:           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
5284:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5285:           remotePointsNew[m].rank  = rrank;
5286:         }
5287:         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (cMax                            - cStart)*3     + (p  - cMax);
5288:         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]);
5289:         remotePointsNew[m].rank  = rrank;
5290:         ++m;
5291:       }
5292:       break;
5293:     case 5:
5294:       /* Simplicial 3D */
5295:       if ((p >= vStart) && (p < vEnd)) {
5296:         /* Old vertices stay the same */
5297:         localPointsNew[m]        = vStartNew     + (p  - vStart);
5298:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5299:         remotePointsNew[m].rank  = rrank;
5300:         ++m;
5301:       } else if ((p >= eStart) && (p < eEnd)) {
5302:         /* Old edges add new edges and vertex */
5303:         for (r = 0; r < 2; ++r, ++m) {
5304:           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
5305:           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
5306:           remotePointsNew[m].rank  = rrank;
5307:         }
5308:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
5309:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
5310:         remotePointsNew[m].rank  = rrank;
5311:         ++m;
5312:       } else if ((p >= fStart) && (p < fEnd)) {
5313:         /* Old faces add new faces and face edges */
5314:         for (r = 0; r < 4; ++r, ++m) {
5315:           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
5316:           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
5317:           remotePointsNew[m].rank  = rrank;
5318:         }
5319:         for (r = 0; r < 3; ++r, ++m) {
5320:           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (p  - fStart)*3     + r;
5321:           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + (rp - rfStart[n])*3 + r;
5322:           remotePointsNew[m].rank  = rrank;
5323:         }
5324:       } else if ((p >= cStart) && (p < cEnd)) {
5325:         /* Old cells add new cells and interior faces and edges */
5326:         for (r = 0; r < 8; ++r, ++m) {
5327:           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
5328:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
5329:           remotePointsNew[m].rank  = rrank;
5330:         }
5331:         for (r = 0; r < 8; ++r, ++m) {
5332:           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*4                    + (p  - cStart)*8     + r;
5333:           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*8 + r;
5334:           remotePointsNew[m].rank  = rrank;
5335:         }
5336:         for (r = 0; r < 1; ++r, ++m) {
5337:           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (fEnd - fStart)*3                    + (p  - cStart)*1     + r;
5338:           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + rdepthSizeOld[n*(depth+1)+depth-1]*3 + (rp - rcStart[n])*1 + r;
5339:           remotePointsNew[m].rank  = rrank;
5340:         }
5341:       }
5342:       break;
5343:     case 7:
5344:       /* Hybrid Simplicial 3D */
5345:       if ((p >= vStart) && (p < vEnd)) {
5346:         /* Interior vertices stay the same */
5347:         localPointsNew[m]        = vStartNew     + (p  - vStart);
5348:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5349:         remotePointsNew[m].rank  = rrank;
5350:         ++m;
5351:       } else if ((p >= eStart) && (p < eMax)) {
5352:         /* Interior edges add new edges and vertex */
5353:         for (r = 0; r < 2; ++r, ++m) {
5354:           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
5355:           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
5356:           remotePointsNew[m].rank  = rrank;
5357:         }
5358:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
5359:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
5360:         remotePointsNew[m].rank  = rrank;
5361:         ++m;
5362:       } else if ((p >= eMax) && (p < eEnd)) {
5363:         /* Hybrid edges stay the same */
5364:         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (cMax                            - cStart)     + (p  - eMax);
5365:         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]);
5366:         remotePointsNew[m].rank  = rrank;
5367:         ++m;
5368:       } else if ((p >= fStart) && (p < fMax)) {
5369:         /* Interior faces add new faces and edges */
5370:         for (r = 0; r < 4; ++r, ++m) {
5371:           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
5372:           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
5373:           remotePointsNew[m].rank  = rrank;
5374:         }
5375:         for (r = 0; r < 3; ++r, ++m) {
5376:           localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (p  - fStart)*3     + r;
5377:           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*3 + r;
5378:           remotePointsNew[m].rank  = rrank;
5379:         }
5380:       } else if ((p >= fMax) && (p < fEnd)) {
5381:         /* Hybrid faces add new faces and edges */
5382:         for (r = 0; r < 2; ++r, ++m) {
5383:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (p  - fMax)*2                              + r;
5384:           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;
5385:           remotePointsNew[m].rank  = rrank;
5386:         }
5387:         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (cMax                            - cStart)     + (p  - fMax);
5388:         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]);
5389:         remotePointsNew[m].rank  = rrank;
5390:         ++m;
5391:       } else if ((p >= cStart) && (p < cMax)) {
5392:         /* Interior cells add new cells, faces, and edges */
5393:         for (r = 0; r < 8; ++r, ++m) {
5394:           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
5395:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
5396:           remotePointsNew[m].rank  = rrank;
5397:         }
5398:         for (r = 0; r < 8; ++r, ++m) {
5399:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (p  - cStart)*8     + r;
5400:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*8 + r;
5401:           remotePointsNew[m].rank  = rrank;
5402:         }
5403:         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (p  - cStart)*1     + r;
5404:         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;
5405:         remotePointsNew[m].rank  = rrank;
5406:         ++m;
5407:       } else if ((p >= cMax) && (p < cEnd)) {
5408:         /* Hybrid cells add new cells and faces */
5409:         for (r = 0; r < 4; ++r, ++m) {
5410:           localPointsNew[m]        = cStartNew     + (cMax                            - cStart)*8     + (p  - cMax)*4                            + r;
5411:           remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
5412:           remotePointsNew[m].rank  = rrank;
5413:         }
5414:         for (r = 0; r < 3; ++r, ++m) {
5415:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (fEnd                                          - fMax)*2                              + (p  - cMax)*3                            + r;
5416:           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;
5417:           remotePointsNew[m].rank  = rrank;
5418:         }
5419:       }
5420:       break;
5421:     case 6:
5422:       /* Hex 3D */
5423:       if ((p >= vStart) && (p < vEnd)) {
5424:         /* Old vertices stay the same */
5425:         localPointsNew[m]        = vStartNew     + (p  - vStart);
5426:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5427:         remotePointsNew[m].rank  = rrank;
5428:         ++m;
5429:       } else if ((p >= eStart) && (p < eEnd)) {
5430:         /* Old edges add new edges and vertex */
5431:         for (r = 0; r < 2; ++r, ++m) {
5432:           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
5433:           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
5434:           remotePointsNew[m].rank  = rrank;
5435:         }
5436:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
5437:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
5438:         remotePointsNew[m].rank  = rrank;
5439:         ++m;
5440:       } else if ((p >= fStart) && (p < fEnd)) {
5441:         /* Old faces add new faces, edges, and vertex */
5442:         for (r = 0; r < 4; ++r, ++m) {
5443:           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
5444:           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
5445:           remotePointsNew[m].rank  = rrank;
5446:         }
5447:         for (r = 0; r < 4; ++r, ++m) {
5448:           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (p  - fStart)*4     + r;
5449:           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + (rp - rfStart[n])*4 + r;
5450:           remotePointsNew[m].rank  = rrank;
5451:         }
5452:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (eEnd - eStart)              + (p  - fStart);
5453:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+1] + (rp - rfStart[n]);
5454:         remotePointsNew[m].rank  = rrank;
5455:         ++m;
5456:       } else if ((p >= cStart) && (p < cEnd)) {
5457:         /* Old cells add new cells, faces, edges, and vertex */
5458:         for (r = 0; r < 8; ++r, ++m) {
5459:           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
5460:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
5461:           remotePointsNew[m].rank  = rrank;
5462:         }
5463:         for (r = 0; r < 12; ++r, ++m) {
5464:           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*4                    + (p  - cStart)*12     + r;
5465:           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*12 + r;
5466:           remotePointsNew[m].rank  = rrank;
5467:         }
5468:         for (r = 0; r < 6; ++r, ++m) {
5469:           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (fEnd - fStart)*4                    + (p  - cStart)*6     + r;
5470:           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*6 + r;
5471:           remotePointsNew[m].rank  = rrank;
5472:         }
5473:         for (r = 0; r < 1; ++r, ++m) {
5474:           localPointsNew[m]        = vStartNew     + (eEnd - eStart)              + (fEnd - fStart)                    + (p  - cStart)     + r;
5475:           remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+1] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]) + r;
5476:           remotePointsNew[m].rank  = rrank;
5477:         }
5478:       }
5479:       break;
5480:     case 8:
5481:       /* Hybrid Hex 3D */
5482:       if ((p >= vStart) && (p < vEnd)) {
5483:         /* Interior vertices stay the same */
5484:         localPointsNew[m]        = vStartNew     + (p  - vStart);
5485:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5486:         remotePointsNew[m].rank  = rrank;
5487:         ++m;
5488:       } else if ((p >= eStart) && (p < eMax)) {
5489:         /* Interior edges add new edges and vertex */
5490:         for (r = 0; r < 2; ++r, ++m) {
5491:           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
5492:           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
5493:           remotePointsNew[m].rank  = rrank;
5494:         }
5495:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
5496:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
5497:         remotePointsNew[m].rank  = rrank;
5498:         ++m;
5499:       } else if ((p >= eMax) && (p < eEnd)) {
5500:         /* Hybrid edges stay the same */
5501:         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (cMax                            - cStart)*6     + (p  - eMax);
5502:         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]);
5503:         remotePointsNew[m].rank  = rrank;
5504:         ++m;
5505:       } else if ((p >= fStart) && (p < fMax)) {
5506:         /* Interior faces add new faces, edges, and vertex */
5507:         for (r = 0; r < 4; ++r, ++m) {
5508:           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
5509:           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
5510:           remotePointsNew[m].rank  = rrank;
5511:         }
5512:         for (r = 0; r < 4; ++r, ++m) {
5513:           localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (p  - fStart)*4     + r;
5514:           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*4 + r;
5515:           remotePointsNew[m].rank  = rrank;
5516:         }
5517:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (eMax                        - eStart)     + (p  - fStart);
5518:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rp - rfStart[n]);
5519:         remotePointsNew[m].rank  = rrank;
5520:         ++m;
5521:       } else if ((p >= fMax) && (p < fEnd)) {
5522:         /* Hybrid faces add new faces and edges */
5523:         for (r = 0; r < 2; ++r, ++m) {
5524:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (p  - fMax)*2                              + r;
5525:           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;
5526:           remotePointsNew[m].rank  = rrank;
5527:         }
5528:         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (cMax                            - cStart)*6     + (fEnd                                          - fMax);
5529:         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]);
5530:         remotePointsNew[m].rank  = rrank;
5531:         ++m;
5532:       } else if ((p >= cStart) && (p < cMax)) {
5533:         /* Interior cells add new cells, faces, edges, and vertex */
5534:         for (r = 0; r < 8; ++r, ++m) {
5535:           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
5536:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
5537:           remotePointsNew[m].rank  = rrank;
5538:         }
5539:         for (r = 0; r < 12; ++r, ++m) {
5540:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (p  - cStart)*12     + r;
5541:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*12 + r;
5542:           remotePointsNew[m].rank  = rrank;
5543:         }
5544:         for (r = 0; r < 6; ++r, ++m) {
5545:           localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (p  - cStart)*6     + r;
5546:           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;
5547:           remotePointsNew[m].rank  = rrank;
5548:         }
5549:         for (r = 0; r < 1; ++r, ++m) {
5550:           localPointsNew[m]        = vStartNew     + (eMax                        - eStart)     + (fMax                              - fStart)     + (p  - cStart)     + r;
5551:           remotePointsNew[m].index = rvStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]) + r;
5552:           remotePointsNew[m].rank  = rrank;
5553:         }
5554:       } else if ((p >= cMax) && (p < cEnd)) {
5555:         /* Hybrid cells add new cells, faces, and edges */
5556:         for (r = 0; r < 4; ++r, ++m) {
5557:           localPointsNew[m]        = cStartNew     + (cMax                            - cStart)*8     + (p  - cMax)*4                            + r;
5558:           remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
5559:           remotePointsNew[m].rank  = rrank;
5560:         }
5561:         for (r = 0; r < 4; ++r, ++m) {
5562:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (fEnd                                          - fMax)*2                              + (p  - cMax)*4                            + r;
5563:           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;
5564:           remotePointsNew[m].rank  = rrank;
5565:         }
5566:         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (cMax                            - cStart)*6     + (fEnd                                          - fMax)                              + (p  - cMax);
5567:         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]);
5568:         remotePointsNew[m].rank  = rrank;
5569:         ++m;
5570:       }
5571:       break;
5572:     default:
5573:       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5574:     }
5575:   }
5576:   if (m != numLeavesNew) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of leaf point %d should be %d", m, numLeavesNew);
5577:   ISRestoreIndices(processRanks, &neighbors);
5578:   ISDestroy(&processRanks);
5579:   PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);
5580:   PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);
5581:   PetscFree7(depthSizeOld,rdepthSizeOld,rdepthMaxOld,rvStart,reStart,rfStart,rcStart);
5582:   return(0);
5583: }

5587: static PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
5588: {
5589:   PetscInt       numLabels, l;
5590:   PetscInt       depth, newp, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r;
5591:   PetscInt       cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;

5595:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
5596:   DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
5597:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
5598:   DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
5599:   DMPlexGetDepth(dm, &depth);
5600:   if (refiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
5601:   DMPlexGetNumLabels(dm, &numLabels);
5602:   DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
5603:   switch (refiner) {
5604:   case 0: break;
5605:   case 7:
5606:   case 8:
5607:     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
5608:   case 3:
5609:   case 4:
5610:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
5611:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
5612:   }
5613:   for (l = 0; l < numLabels; ++l) {
5614:     DMLabel         label, labelNew;
5615:     const char     *lname;
5616:     PetscBool       isDepth;
5617:     IS              valueIS;
5618:     const PetscInt *values;
5619:     PetscInt        numValues, val;

5621:     DMPlexGetLabelName(dm, l, &lname);
5622:     PetscStrcmp(lname, "depth", &isDepth);
5623:     if (isDepth) continue;
5624:     DMPlexCreateLabel(rdm, lname);
5625:     DMPlexGetLabel(dm, lname, &label);
5626:     DMPlexGetLabel(rdm, lname, &labelNew);
5627:     DMLabelGetValueIS(label, &valueIS);
5628:     ISGetLocalSize(valueIS, &numValues);
5629:     ISGetIndices(valueIS, &values);
5630:     for (val = 0; val < numValues; ++val) {
5631:       IS              pointIS;
5632:       const PetscInt *points;
5633:       PetscInt        numPoints, n;

5635:       DMLabelGetStratumIS(label, values[val], &pointIS);
5636:       ISGetLocalSize(pointIS, &numPoints);
5637:       ISGetIndices(pointIS, &points);
5638:       for (n = 0; n < numPoints; ++n) {
5639:         const PetscInt p = points[n];
5640:         switch (refiner) {
5641:         case 1:
5642:           /* Simplicial 2D */
5643:           if ((p >= vStart) && (p < vEnd)) {
5644:             /* Old vertices stay the same */
5645:             newp = vStartNew + (p - vStart);
5646:             DMLabelSetValue(labelNew, newp, values[val]);
5647:           } else if ((p >= fStart) && (p < fEnd)) {
5648:             /* Old faces add new faces and vertex */
5649:             newp = vStartNew + (vEnd - vStart) + (p - fStart);
5650:             DMLabelSetValue(labelNew, newp, values[val]);
5651:             for (r = 0; r < 2; ++r) {
5652:               newp = fStartNew + (p - fStart)*2 + r;
5653:               DMLabelSetValue(labelNew, newp, values[val]);
5654:             }
5655:           } else if ((p >= cStart) && (p < cEnd)) {
5656:             /* Old cells add new cells and interior faces */
5657:             for (r = 0; r < 4; ++r) {
5658:               newp = cStartNew + (p - cStart)*4 + r;
5659:               DMLabelSetValue(labelNew, newp, values[val]);
5660:             }
5661:             for (r = 0; r < 3; ++r) {
5662:               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
5663:               DMLabelSetValue(labelNew, newp, values[val]);
5664:             }
5665:           }
5666:           break;
5667:         case 2:
5668:           /* Hex 2D */
5669:           if ((p >= vStart) && (p < vEnd)) {
5670:             /* Old vertices stay the same */
5671:             newp = vStartNew + (p - vStart);
5672:             DMLabelSetValue(labelNew, newp, values[val]);
5673:           } else if ((p >= fStart) && (p < fEnd)) {
5674:             /* Old faces add new faces and vertex */
5675:             newp = vStartNew + (vEnd - vStart) + (p - fStart);
5676:             DMLabelSetValue(labelNew, newp, values[val]);
5677:             for (r = 0; r < 2; ++r) {
5678:               newp = fStartNew + (p - fStart)*2 + r;
5679:               DMLabelSetValue(labelNew, newp, values[val]);
5680:             }
5681:           } else if ((p >= cStart) && (p < cEnd)) {
5682:             /* Old cells add new cells and interior faces and vertex */
5683:             for (r = 0; r < 4; ++r) {
5684:               newp = cStartNew + (p - cStart)*4 + r;
5685:               DMLabelSetValue(labelNew, newp, values[val]);
5686:             }
5687:             for (r = 0; r < 4; ++r) {
5688:               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
5689:               DMLabelSetValue(labelNew, newp, values[val]);
5690:             }
5691:             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
5692:             DMLabelSetValue(labelNew, newp, values[val]);
5693:           }
5694:           break;
5695:         case 3:
5696:           /* Hybrid simplicial 2D */
5697:           if ((p >= vStart) && (p < vEnd)) {
5698:             /* Old vertices stay the same */
5699:             newp = vStartNew + (p - vStart);
5700:             DMLabelSetValue(labelNew, newp, values[val]);
5701:           } else if ((p >= fStart) && (p < fMax)) {
5702:             /* Old interior faces add new faces and vertex */
5703:             newp = vStartNew + (vEnd - vStart) + (p - fStart);
5704:             DMLabelSetValue(labelNew, newp, values[val]);
5705:             for (r = 0; r < 2; ++r) {
5706:               newp = fStartNew + (p - fStart)*2 + r;
5707:               DMLabelSetValue(labelNew, newp, values[val]);
5708:             }
5709:           } else if ((p >= fMax) && (p < fEnd)) {
5710:             /* Old hybrid faces stay the same */
5711:             newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
5712:             DMLabelSetValue(labelNew, newp, values[val]);
5713:           } else if ((p >= cStart) && (p < cMax)) {
5714:             /* Old interior cells add new cells and interior faces */
5715:             for (r = 0; r < 4; ++r) {
5716:               newp = cStartNew + (p - cStart)*4 + r;
5717:               DMLabelSetValue(labelNew, newp, values[val]);
5718:             }
5719:             for (r = 0; r < 3; ++r) {
5720:               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
5721:               DMLabelSetValue(labelNew, newp, values[val]);
5722:             }
5723:           } else if ((p >= cMax) && (p < cEnd)) {
5724:             /* Old hybrid cells add new cells and hybrid face */
5725:             for (r = 0; r < 2; ++r) {
5726:               newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
5727:               DMLabelSetValue(labelNew, newp, values[val]);
5728:             }
5729:             newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
5730:             DMLabelSetValue(labelNew, newp, values[val]);
5731:           }
5732:           break;
5733:         case 5:
5734:           /* Simplicial 3D */
5735:           if ((p >= vStart) && (p < vEnd)) {
5736:             /* Old vertices stay the same */
5737:             newp = vStartNew + (p - vStart);
5738:             DMLabelSetValue(labelNew, newp, values[val]);
5739:           } else if ((p >= eStart) && (p < eEnd)) {
5740:             /* Old edges add new edges and vertex */
5741:             for (r = 0; r < 2; ++r) {
5742:               newp = eStartNew + (p - eStart)*2 + r;
5743:               DMLabelSetValue(labelNew, newp, values[val]);
5744:             }
5745:             newp = vStartNew + (vEnd - vStart) + (p - eStart);
5746:             DMLabelSetValue(labelNew, newp, values[val]);
5747:           } else if ((p >= fStart) && (p < fEnd)) {
5748:             /* Old faces add new faces and edges */
5749:             for (r = 0; r < 4; ++r) {
5750:               newp = fStartNew + (p - fStart)*4 + r;
5751:               DMLabelSetValue(labelNew, newp, values[val]);
5752:             }
5753:             for (r = 0; r < 3; ++r) {
5754:               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
5755:               DMLabelSetValue(labelNew, newp, values[val]);
5756:             }
5757:           } else if ((p >= cStart) && (p < cEnd)) {
5758:             /* Old cells add new cells and interior faces and edges */
5759:             for (r = 0; r < 8; ++r) {
5760:               newp = cStartNew + (p - cStart)*8 + r;
5761:               DMLabelSetValue(labelNew, newp, values[val]);
5762:             }
5763:             for (r = 0; r < 8; ++r) {
5764:               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*8 + r;
5765:               DMLabelSetValue(labelNew, newp, values[val]);
5766:             }
5767:             for (r = 0; r < 1; ++r) {
5768:               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*1 + r;
5769:               DMLabelSetValue(labelNew, newp, values[val]);
5770:             }
5771:           }
5772:           break;
5773:         case 7:
5774:           /* Hybrid Simplicial 3D */
5775:           if ((p >= vStart) && (p < vEnd)) {
5776:             /* Interior vertices stay the same */
5777:             newp = vStartNew + (p - vStart);
5778:             DMLabelSetValue(labelNew, newp, values[val]);
5779:           } else if ((p >= eStart) && (p < eMax)) {
5780:             /* Interior edges add new edges and vertex */
5781:             for (r = 0; r < 2; ++r) {
5782:               newp = eStartNew + (p - eStart)*2 + r;
5783:               DMLabelSetValue(labelNew, newp, values[val]);
5784:             }
5785:             newp = vStartNew + (vEnd - vStart) + (p - eStart);
5786:             DMLabelSetValue(labelNew, newp, values[val]);
5787:           } else if ((p >= eMax) && (p < eEnd)) {
5788:             /* Hybrid edges stay the same */
5789:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - eMax);
5790:             DMLabelSetValue(labelNew, newp, values[val]);
5791:           } else if ((p >= fStart) && (p < fMax)) {
5792:             /* Interior faces add new faces and edges */
5793:             for (r = 0; r < 4; ++r) {
5794:               newp = fStartNew + (p - fStart)*4 + r;
5795:               DMLabelSetValue(labelNew, newp, values[val]);
5796:             }
5797:             for (r = 0; r < 3; ++r) {
5798:               newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
5799:               DMLabelSetValue(labelNew, newp, values[val]);
5800:             }
5801:           } else if ((p >= fMax) && (p < fEnd)) {
5802:             /* Hybrid faces add new faces and edges */
5803:             for (r = 0; r < 2; ++r) {
5804:               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (p - fMax)*2 + r;
5805:               DMLabelSetValue(labelNew, newp, values[val]);
5806:             }
5807:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - fMax);
5808:             DMLabelSetValue(labelNew, newp, values[val]);
5809:           } else if ((p >= cStart) && (p < cMax)) {
5810:             /* Interior cells add new cells, faces, and edges */
5811:             for (r = 0; r < 8; ++r) {
5812:               newp = cStartNew + (p - cStart)*8 + r;
5813:               DMLabelSetValue(labelNew, newp, values[val]);
5814:             }
5815:             for (r = 0; r < 8; ++r) {
5816:               newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*8 + r;
5817:               DMLabelSetValue(labelNew, newp, values[val]);
5818:             }
5819:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart);
5820:             DMLabelSetValue(labelNew, newp, values[val]);
5821:           } else if ((p >= cMax) && (p < cEnd)) {
5822:             /* Hybrid cells add new cells and faces */
5823:             for (r = 0; r < 4; ++r) {
5824:               newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
5825:               DMLabelSetValue(labelNew, newp, values[val]);
5826:             }
5827:             for (r = 0; r < 3; ++r) {
5828:               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
5829:               DMLabelSetValue(labelNew, newp, values[val]);
5830:             }
5831:           }
5832:           break;
5833:         case 6:
5834:           /* Hex 3D */
5835:           if ((p >= vStart) && (p < vEnd)) {
5836:             /* Old vertices stay the same */
5837:             newp = vStartNew + (p - vStart);
5838:             DMLabelSetValue(labelNew, newp, values[val]);
5839:           } else if ((p >= eStart) && (p < eEnd)) {
5840:             /* Old edges add new edges and vertex */
5841:             for (r = 0; r < 2; ++r) {
5842:               newp = eStartNew + (p - eStart)*2 + r;
5843:               DMLabelSetValue(labelNew, newp, values[val]);
5844:             }
5845:             newp = vStartNew + (vEnd - vStart) + (p - eStart);
5846:             DMLabelSetValue(labelNew, newp, values[val]);
5847:           } else if ((p >= fStart) && (p < fEnd)) {
5848:             /* Old faces add new faces, edges, and vertex */
5849:             for (r = 0; r < 4; ++r) {
5850:               newp = fStartNew + (p - fStart)*4 + r;
5851:               DMLabelSetValue(labelNew, newp, values[val]);
5852:             }
5853:             for (r = 0; r < 4; ++r) {
5854:               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*4 + r;
5855:               DMLabelSetValue(labelNew, newp, values[val]);
5856:             }
5857:             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (p - fStart);
5858:             DMLabelSetValue(labelNew, newp, values[val]);
5859:           } else if ((p >= cStart) && (p < cEnd)) {
5860:             /* Old cells add new cells, faces, edges, and vertex */
5861:             for (r = 0; r < 8; ++r) {
5862:               newp = cStartNew + (p - cStart)*8 + r;
5863:               DMLabelSetValue(labelNew, newp, values[val]);
5864:             }
5865:             for (r = 0; r < 12; ++r) {
5866:               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*12 + r;
5867:               DMLabelSetValue(labelNew, newp, values[val]);
5868:             }
5869:             for (r = 0; r < 6; ++r) {
5870:               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (p - cStart)*6 + r;
5871:               DMLabelSetValue(labelNew, newp, values[val]);
5872:             }
5873:             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (p - cStart);
5874:             DMLabelSetValue(labelNew, newp, values[val]);
5875:           }
5876:           break;
5877:         case 8:
5878:           /* Hybrid Hex 3D */
5879:           if ((p >= vStart) && (p < vEnd)) {
5880:             /* Interior vertices stay the same */
5881:             newp = vStartNew + (p - vStart);
5882:             DMLabelSetValue(labelNew, newp, values[val]);
5883:           } else if ((p >= eStart) && (p < eMax)) {
5884:             /* Interior edges add new edges and vertex */
5885:             for (r = 0; r < 2; ++r) {
5886:               newp = eStartNew + (p - eStart)*2 + r;
5887:               DMLabelSetValue(labelNew, newp, values[val]);
5888:             }
5889:             newp = vStartNew + (vEnd - vStart) + (p - eStart);
5890:             DMLabelSetValue(labelNew, newp, values[val]);
5891:           } else if ((p >= eMax) && (p < eEnd)) {
5892:             /* Hybrid edges stay the same */
5893:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - eMax);
5894:             DMLabelSetValue(labelNew, newp, values[val]);
5895:           } else if ((p >= fStart) && (p < fMax)) {
5896:             /* Interior faces add new faces, edges, and vertex */
5897:             for (r = 0; r < 4; ++r) {
5898:               newp = fStartNew + (p - fStart)*4 + r;
5899:               DMLabelSetValue(labelNew, newp, values[val]);
5900:             }
5901:             for (r = 0; r < 4; ++r) {
5902:               newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*4 + r;
5903:               DMLabelSetValue(labelNew, newp, values[val]);
5904:             }
5905:             newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (p - fStart);
5906:             DMLabelSetValue(labelNew, newp, values[val]);
5907:           } else if ((p >= fMax) && (p < fEnd)) {
5908:             /* Hybrid faces add new faces and edges */
5909:             for (r = 0; r < 2; ++r) {
5910:               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (p - fMax)*2 + r;
5911:               DMLabelSetValue(labelNew, newp, values[val]);
5912:             }
5913:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - fMax);
5914:             DMLabelSetValue(labelNew, newp, values[val]);
5915:           } else if ((p >= cStart) && (p < cMax)) {
5916:             /* Interior cells add new cells, faces, edges, and vertex */
5917:             for (r = 0; r < 8; ++r) {
5918:               newp = cStartNew + (p - cStart)*8 + r;
5919:               DMLabelSetValue(labelNew, newp, values[val]);
5920:             }
5921:             for (r = 0; r < 12; ++r) {
5922:               newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*12 + r;
5923:               DMLabelSetValue(labelNew, newp, values[val]);
5924:             }
5925:             for (r = 0; r < 6; ++r) {
5926:               newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (p - cStart)*6 + r;
5927:               DMLabelSetValue(labelNew, newp, values[val]);
5928:             }
5929:             newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (p - cStart);
5930:             DMLabelSetValue(labelNew, newp, values[val]);
5931:           } else if ((p >= cMax) && (p < cEnd)) {
5932:             /* Hybrid cells add new cells, faces, and edges */
5933:             for (r = 0; r < 4; ++r) {
5934:               newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
5935:               DMLabelSetValue(labelNew, newp, values[val]);
5936:             }
5937:             for (r = 0; r < 4; ++r) {
5938:               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (p - cMax)*4 + r;
5939:               DMLabelSetValue(labelNew, newp, values[val]);
5940:             }
5941:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (fEnd - fMax) + (p - cMax);
5942:             DMLabelSetValue(labelNew, newp, values[val]);
5943:           }
5944:           break;
5945:         default:
5946:           SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5947:         }
5948:       }
5949:       ISRestoreIndices(pointIS, &points);
5950:       ISDestroy(&pointIS);
5951:     }
5952:     ISRestoreIndices(valueIS, &values);
5953:     ISDestroy(&valueIS);
5954:     if (0) {
5955:       PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);
5956:       DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);
5957:       PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);
5958:     }
5959:   }
5960:   return(0);
5961: }

5965: /* This will only work for interpolated meshes */
5966: PetscErrorCode DMPlexRefineUniform_Internal(DM dm, CellRefiner cellRefiner, DM *dmRefined)
5967: {
5968:   DM             rdm;
5969:   PetscInt      *depthSize;
5970:   PetscInt       dim, depth = 0, d, pStart = 0, pEnd = 0;

5974:   DMCreate(PetscObjectComm((PetscObject)dm), &rdm);
5975:   DMSetType(rdm, DMPLEX);
5976:   DMPlexGetDimension(dm, &dim);
5977:   DMPlexSetDimension(rdm, dim);
5978:   /* Calculate number of new points of each depth */
5979:   DMPlexGetDepth(dm, &depth);
5980:   PetscMalloc1((depth+1), &depthSize);
5981:   PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));
5982:   CellRefinerGetSizes(cellRefiner, dm, depthSize);
5983:   /* Step 1: Set chart */
5984:   for (d = 0; d <= depth; ++d) pEnd += depthSize[d];
5985:   DMPlexSetChart(rdm, pStart, pEnd);
5986:   /* Step 2: Set cone/support sizes */
5987:   CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);
5988:   /* Step 3: Setup refined DM */
5989:   DMSetUp(rdm);
5990:   /* Step 4: Set cones and supports */
5991:   CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);
5992:   /* Step 5: Stratify */
5993:   DMPlexStratify(rdm);
5994:   /* Step 6: Set coordinates for vertices */
5995:   CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);
5996:   /* Step 7: Create pointSF */
5997:   CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);
5998:   /* Step 8: Create labels */
5999:   CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);
6000:   PetscFree(depthSize);

6002:   *dmRefined = rdm;
6003:   return(0);
6004: }

6008: PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
6009: {
6010:   DM_Plex *mesh = (DM_Plex*) dm->data;

6014:   mesh->refinementUniform = refinementUniform;
6015:   return(0);
6016: }

6020: PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
6021: {
6022:   DM_Plex *mesh = (DM_Plex*) dm->data;

6027:   *refinementUniform = mesh->refinementUniform;
6028:   return(0);
6029: }

6033: PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
6034: {
6035:   DM_Plex *mesh = (DM_Plex*) dm->data;

6039:   mesh->refinementLimit = refinementLimit;
6040:   return(0);
6041: }

6045: PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
6046: {
6047:   DM_Plex *mesh = (DM_Plex*) dm->data;

6052:   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
6053:   *refinementLimit = mesh->refinementLimit;
6054:   return(0);
6055: }

6059: PetscErrorCode DMPlexGetCellRefiner_Internal(DM dm, CellRefiner *cellRefiner)
6060: {
6061:   PetscInt       dim, cStart, cEnd, coneSize, cMax;

6065:   DMPlexGetDimension(dm, &dim);
6066:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
6067:   if (cEnd <= cStart) {*cellRefiner = 0; return(0);}
6068:   DMPlexGetConeSize(dm, cStart, &coneSize);
6069:   DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);
6070:   switch (dim) {
6071:   case 2:
6072:     switch (coneSize) {
6073:     case 3:
6074:       if (cMax >= 0) *cellRefiner = 3; /* Hybrid */
6075:       else *cellRefiner = 1; /* Triangular */
6076:       break;
6077:     case 4:
6078:       if (cMax >= 0) *cellRefiner = 4; /* Hybrid */
6079:       else *cellRefiner = 2; /* Quadrilateral */
6080:       break;
6081:     default:
6082:       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
6083:     }
6084:     break;
6085:   case 3:
6086:     switch (coneSize) {
6087:     case 4:
6088:       if (cMax >= 0) *cellRefiner = 7; /* Hybrid */
6089:       else *cellRefiner = 5; /* Tetrahedral */
6090:       break;
6091:     case 6:
6092:       if (cMax >= 0) *cellRefiner = 8; /* Hybrid */
6093:       else *cellRefiner = 6; /* hexahedral */
6094:       break;
6095:     default:
6096:       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
6097:     }
6098:     break;
6099:   default:
6100:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim);
6101:   }
6102:   return(0);
6103: }