Actual source code: plexrefine.c

petsc-3.12.2 2019-11-22
Report Typos and Errors
  1:  #include <petsc/private/dmpleximpl.h>
  2:  #include <petscsf.h>

  4: const char * const CellRefiners[] = {"NOOP", "SIMPLEX_1D", "SIMPLEX_2D", "HYBRID_SIMPLEX_2D", "SIMPLEX_TO_HEX_2D", "HYBRID_SIMPLEX_TO_HEX_2D", "HEX_2D", "HYBRID_HEX_2D",
  5:                                      "SIMPLEX_3D", "HYBRID_SIMPLEX_3D", "SIMPLEX_TO_HEX_3D", "HYBRID_SIMPLEX_TO_HEX_3D", "HEX_3D", "HYBRID_HEX_3D", "CellRefiners", "REFINER_", 0};

  7: PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart)
  8: {
 10:   if (cStart) *cStart = 0;
 11:   if (vStart) *vStart = depth < 0 ? 0 : depthSize[depth];
 12:   if (fStart) *fStart = depth < 0 ? 0 : depthSize[depth] + depthSize[0];
 13:   if (eStart) *eStart = depth < 0 ? 0 : depthSize[depth] + depthSize[0] + depthSize[depth-1];
 14:   return(0);
 15: }

 17: PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd)
 18: {
 20:   if (cEnd) *cEnd = depth < 0 ? 0 : depthSize[depth];
 21:   if (vEnd) *vEnd = depth < 0 ? 0 : depthSize[depth] + depthSize[0];
 22:   if (fEnd) *fEnd = depth < 0 ? 0 : depthSize[depth] + depthSize[0] + depthSize[depth-1];
 23:   if (eEnd) *eEnd = depth < 0 ? 0 : depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1];
 24:   return(0);
 25: }

 27: /*
 28:   Note that j and invj are non-square:
 29:          v0 + j x_face = x_cell
 30:     invj (x_cell - v0) = x_face
 31: */
 32: PetscErrorCode CellRefinerGetAffineFaceTransforms_Internal(CellRefiner refiner, PetscInt *numFaces, PetscReal *v0[], PetscReal *jac[], PetscReal *invjac[], PetscReal *detj[])
 33: {
 34:   PetscReal     *v = NULL, *j = NULL, *invj = NULL, *dj = NULL;
 35:   PetscInt       cdim, fdim;

 39:   switch (refiner) {
 40:   case REFINER_NOOP: break;
 41:   case REFINER_SIMPLEX_2D:
 42:     /*
 43:      2
 44:      |\
 45:      | \
 46:      |  \
 47:      |   \
 48:      |    \
 49:      |     \
 50:      |      \
 51:      2       1
 52:      |        \
 53:      |         \
 54:      |          \
 55:      0---0-------1
 56:      */
 57:     cdim = 2;
 58:     fdim = 1;
 59:     if (numFaces) *numFaces = 3;
 60:     if (v0) {
 61:       PetscMalloc1(3*cdim,      &v);
 62:       PetscMalloc1(3*cdim*fdim, &j);
 63:       PetscMalloc1(3*cdim*fdim, &invj);
 64:       PetscMalloc1(3,           &dj);
 65:       /* 0 */
 66:       v[0+0] =  0.0; v[0+1] = -1.0;
 67:       j[0+0] =  1.0;
 68:       j[0+1] =  0.0;
 69:       invj[0+0] = 1.0; invj[0+1] = 0.0;
 70:       dj[0]  = 1.0;
 71:       /* 1 */
 72:       v[2+0] =  0.0; v[2+1] =  0.0;
 73:       j[2+0] = -1.0;
 74:       j[2+1] =  1.0;
 75:       invj[2+0] = -0.5; invj[2+1] = 0.5;
 76:       dj[1]  = 1.414213562373095;
 77:       /* 2 */
 78:       v[4+0] = -1.0; v[4+1] =  0.0;
 79:       j[4+0] =  0.0;
 80:       j[4+1] = -1.0;
 81:       invj[4+0] = 0.0; invj[4+1] = -1.0;
 82:       dj[2]  = 1.0;
 83:     }
 84:     break;
 85:   case REFINER_HEX_2D:
 86:     /*
 87:      3---------2---------2
 88:      |                   |
 89:      |                   |
 90:      |                   |
 91:      3                   1
 92:      |                   |
 93:      |                   |
 94:      |                   |
 95:      0---------0---------1
 96:      */
 97:     cdim = 2;
 98:     fdim = 1;
 99:     if (numFaces) *numFaces = 4;
100:     if (v0) {
101:       PetscMalloc1(4*cdim,      &v);
102:       PetscMalloc1(4*cdim*fdim, &j);
103:       PetscMalloc1(4*cdim*fdim, &invj);
104:       PetscMalloc1(4,           &dj);
105:       /* 0 */
106:       v[0+0] =  0.0; v[0+1] = -1.0;
107:       j[0+0] =  1.0;
108:       j[0+1] =  0.0;
109:       invj[0+0] =  1.0; invj[0+1] =  0.0;
110:       dj[0]  = 1.0;
111:       /* 1 */
112:       v[2+0] =  1.0; v[2+1] =  0.0;
113:       j[2+0] =  0.0;
114:       j[2+1] =  1.0;
115:       invj[2+0] =  0.0; invj[2+1] =  1.0;
116:       dj[1]  = 1.0;
117:       /* 2 */
118:       v[4+0] =  0.0; v[4+1] = 1.0;
119:       j[4+0] = -1.0;
120:       j[4+1] =  0.0;
121:       invj[4+0] = -1.0; invj[4+1] =  0.0;
122:       dj[2]  = 1.0;
123:       /* 3 */
124:       v[6+0] = -1.0; v[6+1] =  0.0;
125:       j[6+0] =  0.0;
126:       j[6+1] = -1.0;
127:       invj[6+0] =  0.0; invj[6+1] = -1.0;
128:       dj[3]  = 1.0;
129:     }
130:     break;
131:   default:
132:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
133:   }
134:   if (v0)     {*v0     = v;}
135:   else        {PetscFree(v);}
136:   if (jac)    {*jac    = j;}
137:   else        {PetscFree(j);}
138:   if (invjac) {*invjac = invj;}
139:   else        {PetscFree(invj);}
140:   if (invjac) {*invjac = invj;}
141:   else        {PetscFree(invj);}
142:   if (detj)   {*detj   = dj;}
143:   else        {PetscFree(dj);}
144:   return(0);
145: }

147: /* Gets the affine map from the original cell to each subcell */
148: PetscErrorCode CellRefinerGetAffineTransforms_Internal(CellRefiner refiner, PetscInt *numSubcells, PetscReal *v0[], PetscReal *jac[], PetscReal *invjac[])
149: {
150:   PetscReal     *v = NULL, *j = NULL, *invj = NULL, detJ;
151:   PetscInt       dim, s;

155:   switch (refiner) {
156:   case REFINER_NOOP: break;
157:   case REFINER_SIMPLEX_2D:
158:     /*
159:      2
160:      |\
161:      | \
162:      |  \
163:      |   \
164:      | C  \
165:      |     \
166:      |      \
167:      2---1---1
168:      |\  D  / \
169:      | 2   0   \
170:      |A \ /  B  \
171:      0---0-------1
172:      */
173:     dim = 2;
174:     if (numSubcells) *numSubcells = 4;
175:     if (v0) {
176:       PetscMalloc3(4*dim,&v,4*dim*dim,&j,4*dim*dim,&invj);
177:       /* A */
178:       v[0+0] = -1.0; v[0+1] = -1.0;
179:       j[0+0] =  0.5; j[0+1] =  0.0;
180:       j[0+2] =  0.0; j[0+3] =  0.5;
181:       /* B */
182:       v[2+0] =  0.0; v[2+1] = -1.0;
183:       j[4+0] =  0.5; j[4+1] =  0.0;
184:       j[4+2] =  0.0; j[4+3] =  0.5;
185:       /* C */
186:       v[4+0] = -1.0; v[4+1] =  0.0;
187:       j[8+0] =  0.5; j[8+1] =  0.0;
188:       j[8+2] =  0.0; j[8+3] =  0.5;
189:       /* D */
190:       v[6+0]  =  0.0; v[6+1]  = -1.0;
191:       j[12+0] =  0.0; j[12+1] = -0.5;
192:       j[12+2] =  0.5; j[12+3] =  0.5;
193:       for (s = 0; s < 4; ++s) {
194:         DMPlex_Det2D_Internal(&detJ, &j[s*dim*dim]);
195:         DMPlex_Invert2D_Internal(&invj[s*dim*dim], &j[s*dim*dim], detJ);
196:       }
197:     }
198:     break;
199:   case REFINER_HEX_2D:
200:     /*
201:      3---------2---------2
202:      |         |         |
203:      |    D    2    C    |
204:      |         |         |
205:      3----3----0----1----1
206:      |         |         |
207:      |    A    0    B    |
208:      |         |         |
209:      0---------0---------1
210:      */
211:     dim = 2;
212:     if (numSubcells) *numSubcells = 4;
213:     if (v0) {
214:       PetscMalloc3(4*dim,&v,4*dim*dim,&j,4*dim*dim,&invj);
215:       /* A */
216:       v[0+0] = -1.0; v[0+1] = -1.0;
217:       j[0+0] =  0.5; j[0+1] =  0.0;
218:       j[0+2] =  0.0; j[0+3] =  0.5;
219:       /* B */
220:       v[2+0] =  0.0; v[2+1] = -1.0;
221:       j[4+0] =  0.5; j[4+1] =  0.0;
222:       j[4+2] =  0.0; j[4+3] =  0.5;
223:       /* C */
224:       v[4+0] =  0.0; v[4+1] =  0.0;
225:       j[8+0] =  0.5; j[8+1] =  0.0;
226:       j[8+2] =  0.0; j[8+3] =  0.5;
227:       /* D */
228:       v[6+0]  = -1.0; v[6+1]  =  0.0;
229:       j[12+0] =  0.5; j[12+1] =  0.0;
230:       j[12+2] =  0.0; j[12+3] =  0.5;
231:       for (s = 0; s < 4; ++s) {
232:         DMPlex_Det2D_Internal(&detJ, &j[s*dim*dim]);
233:         DMPlex_Invert2D_Internal(&invj[s*dim*dim], &j[s*dim*dim], detJ);
234:       }
235:     }
236:     break;
237:   case REFINER_HEX_3D:
238:     /*
239:      Bottom (viewed from top)    Top
240:      1---------2---------2       7---------2---------6
241:      |         |         |       |         |         |
242:      |    B    2    C    |       |    H    2    G    |
243:      |         |         |       |         |         |
244:      3----3----0----1----1       3----3----0----1----1
245:      |         |         |       |         |         |
246:      |    A    0    D    |       |    E    0    F    |
247:      |         |         |       |         |         |
248:      0---------0---------3       4---------0---------5
249:      */
250:     break;
251:     dim = 3;
252:     if (numSubcells) *numSubcells = 8;
253:     if (v0) {
254:       PetscMalloc3(4*dim,&v,4*dim*dim,&j,4*dim*dim,&invj);
255:       /* A */
256:       v[0+0] = -1.0; v[0+1] = -1.0; v[0+2] = -1.0;
257:       j[0+0] =  0.5; j[0+1] =  0.0; j[0+2] =  0.0;
258:       j[0+3] =  0.0; j[0+4] =  0.5; j[0+5] =  0.0;
259:       j[0+6] =  0.0; j[0+7] =  0.0; j[0+8] =  0.5;
260:       /* B */
261:       v[3+0] = -1.0; v[3+1] =  0.0; v[3+2] = -1.0;
262:       j[9+0] =  0.5; j[9+1] =  0.0; j[9+2] =  0.0;
263:       j[9+3] =  0.0; j[9+4] =  0.5; j[9+5] =  0.0;
264:       j[9+6] =  0.0; j[9+7] =  0.0; j[9+8] =  0.5;
265:       /* C */
266:       v[6+0] =  0.0; v[6+1] =  0.0; v[6+2] = -1.0;
267:       j[18+0] = 0.5; j[18+1] = 0.0; j[18+2] = 0.0;
268:       j[18+3] = 0.0; j[18+4] = 0.5; j[18+5] = 0.0;
269:       j[18+6] = 0.0; j[18+7] = 0.0; j[18+8] = 0.5;
270:       /* D */
271:       v[9+0] =  0.0; v[9+1] = -1.0; v[9+2] = -1.0;
272:       j[27+0] = 0.5; j[27+1] = 0.0; j[27+2] = 0.0;
273:       j[27+3] = 0.0; j[27+4] = 0.5; j[27+5] = 0.0;
274:       j[27+6] = 0.0; j[27+7] = 0.0; j[27+8] = 0.5;
275:       /* E */
276:       v[12+0] = -1.0; v[12+1] = -1.0; v[12+2] =  0.0;
277:       j[36+0] =  0.5; j[36+1] =  0.0; j[36+2] =  0.0;
278:       j[36+3] =  0.0; j[36+4] =  0.5; j[36+5] =  0.0;
279:       j[36+6] =  0.0; j[36+7] =  0.0; j[36+8] =  0.5;
280:       /* F */
281:       v[15+0] =  0.0; v[15+1] = -1.0; v[15+2] =  0.0;
282:       j[45+0] =  0.5; j[45+1] =  0.0; j[45+2] =  0.0;
283:       j[45+3] =  0.0; j[45+4] =  0.5; j[45+5] =  0.0;
284:       j[45+6] =  0.0; j[45+7] =  0.0; j[45+8] =  0.5;
285:       /* G */
286:       v[18+0] =  0.0; v[18+1] =  0.0; v[18+2] =  0.0;
287:       j[54+0] =  0.5; j[54+1] =  0.0; j[54+2] =  0.0;
288:       j[54+3] =  0.0; j[54+4] =  0.5; j[54+5] =  0.0;
289:       j[54+6] =  0.0; j[54+7] =  0.0; j[54+8] =  0.5;
290:       /* H */
291:       v[21+0] = -1.0; v[21+1] =  0.0; v[21+2] =  0.0;
292:       j[63+0] =  0.5; j[63+1] =  0.0; j[63+2] =  0.0;
293:       j[63+3] =  0.0; j[63+4] =  0.5; j[63+5] =  0.0;
294:       j[63+6] =  0.0; j[63+7] =  0.0; j[63+8] =  0.5;
295:       for (s = 0; s < 8; ++s) {
296:         DMPlex_Det3D_Internal(&detJ, &j[s*dim*dim]);
297:         DMPlex_Invert3D_Internal(&invj[s*dim*dim], &j[s*dim*dim], detJ);
298:       }
299:     }
300:   default:
301:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
302:   }
303:   if (v0) {*v0 = v; *jac = j; *invjac = invj;}
304:   return(0);
305: }

307: PetscErrorCode CellRefinerRestoreAffineTransforms_Internal(CellRefiner refiner, PetscInt *numSubcells, PetscReal *v0[], PetscReal *jac[], PetscReal *invjac[])
308: {

312:   PetscFree3(*v0,*jac,*invjac);
313:   return(0);
314: }

316: /* Should this be here or in the DualSpace somehow? */
317: PetscErrorCode CellRefinerInCellTest_Internal(CellRefiner refiner, const PetscReal point[], PetscBool *inside)
318: {
319:   PetscReal sum = 0.0;
320:   PetscInt  d;

323:   *inside = PETSC_TRUE;
324:   switch (refiner) {
325:   case REFINER_NOOP: break;
326:   case REFINER_SIMPLEX_2D:
327:     for (d = 0; d < 2; ++d) {
328:       if (point[d] < -1.0) {*inside = PETSC_FALSE; break;}
329:       sum += point[d];
330:     }
331:     if (sum > 1.0e-10) {*inside = PETSC_FALSE; break;}
332:     break;
333:   case REFINER_HEX_2D:
334:     for (d = 0; d < 2; ++d) if ((point[d] < -1.00000000001) || (point[d] > 1.000000000001)) {*inside = PETSC_FALSE; break;}
335:     break;
336:   default:
337:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
338:   }
339:   return(0);
340: }

342: static PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[])
343: {
344:   PetscInt       cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax;

348:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
349:   DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
350:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
351:   DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
352:   DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
353:   switch (refiner) {
354:   case REFINER_NOOP:
355:     break;
356:   case REFINER_SIMPLEX_1D:
357:     depthSize[0] = vEnd - vStart + cEnd - cStart;         /* Add a vertex on every cell. */
358:     depthSize[1] = 2*(cEnd - cStart);                     /* Split every cell in 2. */
359:     break;
360:   case REFINER_SIMPLEX_2D:
361:     depthSize[0] = vEnd - vStart + fEnd - fStart;         /* Add a vertex on every face */
362:     depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */
363:     depthSize[2] = 4*(cEnd - cStart);                     /* Every cell split into 4 cells */
364:     break;
365:   case REFINER_HYBRID_SIMPLEX_2D:
366:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
367:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
368:     depthSize[0] = vEnd - vStart + fMax - fStart;                                         /* Add a vertex on every face, but not hybrid faces */
369:     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 */
370:     depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax);                                   /* Interior cells split into 4 cells, hybrid cells split into 2 cells */
371:     break;
372:   case REFINER_SIMPLEX_TO_HEX_2D:
373:     depthSize[0] = vEnd - vStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every face and cell */
374:     depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart);         /* Every face is split into 2 faces and 3 faces are added for each cell */
375:     depthSize[2] = 3*(cEnd - cStart);                             /* Every cell split into 3 cells */
376:     break;
377:   case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
378:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
379:     depthSize[0] = vEnd - vStart + fEnd - fStart + cEnd - cStart;           /* Add a vertex on every face and cell */
380:     depthSize[1] = 2*(fEnd - fStart) + 3*(cMax - cStart) + 4*(cEnd - cMax); /* Every face is split into 2 faces and 3 faces are added for each cell. 4 for each hybrid cell */
381:     depthSize[2] = 3*(cMax - cStart) + 4*(cEnd - cMax);                     /* Every cell split into 3 cells, hybrid cells split in 4 */
382:     break;
383:   case REFINER_HEX_2D:
384:     depthSize[0] = vEnd - vStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every face and cell */
385:     depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart);         /* Every face is split into 2 faces and 4 faces are added for each cell */
386:     depthSize[2] = 4*(cEnd - cStart);                             /* Every cell split into 4 cells */
387:     break;
388:   case REFINER_HYBRID_HEX_2D:
389:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
390:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
391:     /* Quadrilateral */
392:     depthSize[0] = vEnd - vStart + fMax - fStart + cMax - cStart;                 /* Add a vertex on every face and cell */
393:     depthSize[1] = 2*(fMax - fStart) + 4*(cMax - cStart);                         /* Every face is split into 2 faces, and 4 faces are added for each cell */
394:     depthSize[2] = 4*(cMax - cStart);                                             /* Every cell split into 4 cells */
395:     /* Segment Prisms */
396:     depthSize[0] += 0;                                                            /* No hybrid vertices */
397:     depthSize[1] +=   (fEnd - fMax)  +   (cEnd - cMax);                           /* Every hybrid face remains and 1 faces is added for each hybrid cell */
398:     depthSize[2] += 2*(cEnd - cMax);                                              /* Every hybrid cell split into 2 cells */
399:     break;
400:   case REFINER_SIMPLEX_3D:
401:     depthSize[0] =    vEnd - vStart  +    eEnd - eStart;                    /* Add a vertex on every edge */
402:     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 */
403:     depthSize[2] = 4*(fEnd - fStart) + 8*(cEnd - cStart);                   /* Every face split into 4 faces and 8 faces are added for each cell */
404:     depthSize[3] = 8*(cEnd - cStart);                                       /* Every cell split into 8 cells */
405:     break;
406:   case REFINER_HYBRID_SIMPLEX_3D:
407:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
408:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
409:     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
410:     /* Tetrahedra */
411:     depthSize[0]  =    vEnd - vStart  +    eMax - eStart;                    /* Add a vertex on every interior edge */
412:     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 */
413:     depthSize[2]  = 4*(fMax - fStart) + 8*(cMax - cStart);                   /* Every interior face split into 4 faces, 8 faces added for each interior cell */
414:     depthSize[3]  = 8*(cMax - cStart);                                       /* Every interior cell split into 8 cells */
415:     /* Triangular Prisms */
416:     depthSize[0] += 0;                                                       /* No hybrid vertices */
417:     depthSize[1] +=   (eEnd - eMax)   +   (fEnd - fMax);                     /* Every hybrid edge remains, 1 edge for every hybrid face */
418:     depthSize[2] += 2*(fEnd - fMax)   + 3*(cEnd - cMax);                     /* Every hybrid face split into 2 faces and 3 faces are added for each hybrid cell */
419:     depthSize[3] += 4*(cEnd - cMax);                                         /* Every hybrid cell split into 4 cells */
420:     break;
421:   case REFINER_SIMPLEX_TO_HEX_3D:
422:     depthSize[0] = vEnd - vStart + fEnd - fStart + eEnd - eStart + cEnd - cStart; /* Add a vertex on every face, edge and cell */
423:     depthSize[1] = 2*(eEnd - eStart) + 3*(fEnd - fStart) + 4*(cEnd - cStart);     /* Every edge is split into 2 edges, 3 edges are added for each face, and 4 for each cell */
424:     depthSize[2] = 3*(fEnd - fStart) + 6*(cEnd - cStart);                         /* Every face is split into 3 faces and 6 faces are added for each cell */
425:     depthSize[3] = 4*(cEnd - cStart);                                             /* Every cell split into 4 cells */
426:     break;
427:   case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
428:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
429:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
430:     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
431:     /* Tetrahedra */
432:     depthSize[0]  =    vEnd - vStart  +    eMax - eStart  + fMax - fStart + cMax - cStart; /* Add a vertex on every interior edge, face and cell */
433:     depthSize[1]  = 2*(eMax - eStart) + 3*(fMax - fStart) + 4*(cMax - cStart);             /* Every interior edge split into 2 edges, 3 edges added for each interior face, 4 edges for each interior cell */
434:     depthSize[2]  = 3*(fMax - fStart) + 6*(cMax - cStart);                                 /* Every interior face split into 3 faces, 6 faces added for each interior cell */
435:     depthSize[3]  = 4*(cMax - cStart);                                                     /* Every interior cell split into 8 cells */
436:     /* Triangular Prisms */
437:     depthSize[0] += 0;                                                 /* No hybrid vertices */
438:     depthSize[1] +=   (eEnd - eMax) +   (fEnd - fMax) + (cEnd - cMax); /* Every hybrid edge remains, 1 edge for every hybrid face and cell */
439:     depthSize[2] += 2*(fEnd - fMax) + 3*(cEnd - cMax);                 /* Every hybrid face split into 2 faces and 3 faces are added for each hybrid cell */
440:     depthSize[3] += 3*(cEnd - cMax);                                   /* Every hybrid cell split into 3 cells */
441:     break;
442:   case REFINER_HEX_3D:
443:     depthSize[0] = vEnd - vStart + eEnd - eStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every edge, face and cell */
444:     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 */
445:     depthSize[2] = 4*(fEnd - fStart) + 12*(cEnd - cStart);                        /* Every face is split into 4 faces, and 12 faces are added for each cell */
446:     depthSize[3] = 8*(cEnd - cStart);                                             /* Every cell split into 8 cells */
447:     break;
448:   case REFINER_HYBRID_HEX_3D:
449:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
450:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
451:     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
452:     /* Hexahedra */
453:     depthSize[0] = vEnd - vStart + eMax - eStart + fMax - fStart + cMax - cStart; /* Add a vertex on every edge, face and cell */
454:     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 */
455:     depthSize[2] = 4*(fMax - fStart) + 12*(cMax - cStart);                        /* Every face is split into 4 faces, and 12 faces are added for each cell */
456:     depthSize[3] = 8*(cMax - cStart);                                             /* Every cell split into 8 cells */
457:     /* Quadrilateral Prisms */
458:     depthSize[0] += 0;                                                            /* No hybrid vertices */
459:     depthSize[1] +=   (eEnd - eMax)   +   (fEnd - fMax)   +   (cEnd - cMax);      /* Every hybrid edge remains, 1 edge for every hybrid face and hybrid cell */
460:     depthSize[2] += 2*(fEnd - fMax)   + 4*(cEnd - cMax);                          /* Every hybrid face split into 2 faces and 4 faces are added for each hybrid cell */
461:     depthSize[3] += 4*(cEnd - cMax);                                              /* Every hybrid cell split into 4 cells */
462:     break;
463:   default:
464:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
465:   }
466:   return(0);
467: }

469: /* Return triangle edge for orientation o, if it is r for o == 0 */
470: PETSC_STATIC_INLINE PetscInt GetTriEdge_Static(PetscInt o, PetscInt r) {
471:   return (o < 0 ? 2-(o+r) : o+r)%3;
472: }
473: PETSC_STATIC_INLINE PetscInt GetTriEdgeInverse_Static(PetscInt o, PetscInt s) {
474:   return (o < 0 ? 2-(o+s) : 3+s-o)%3;
475: }

477: /* Return triangle subface for orientation o, if it is r for o == 0 */
478: PETSC_STATIC_INLINE PetscInt GetTriSubface_Static(PetscInt o, PetscInt r) {
479:   return (o < 0 ? 3-(o+r) : o+r)%3;
480: }
481: PETSC_STATIC_INLINE PetscInt GetTriSubfaceInverse_Static(PetscInt o, PetscInt s) {
482:   return (o < 0 ? 3-(o+s) : 3+s-o)%3;
483: }

485: /* Return the interior edge number connecting the midpoints of the triangle edges r
486:    and r+1 in the transitive closure for triangle orientation o */
487: PETSC_STATIC_INLINE PetscInt GetTriMidEdge_Static(PetscInt o, PetscInt r) {
488:   return (o < 0 ? 1-(o+r) : o+r)%3;
489: }
490: PETSC_STATIC_INLINE PetscInt GetTriMidEdgeInverse_Static(PetscInt o, PetscInt s) {
491:   return (o < 0 ? 1-(o+s) : 3+s-o)%3;
492: }

494: /* Return the interior edge number connecting the midpoint of the triangle edge r
495:    (in the transitive closure) and the vertex in the interior of the face for triangle orientation o */
496: PETSC_STATIC_INLINE PetscInt GetTriInteriorEdge_Static(PetscInt o, PetscInt r) {
497:   return (o < 0 ? 2-(o+r) : o+r)%3;
498: }
499: PETSC_STATIC_INLINE PetscInt GetTriInteriorEdgeInverse_Static(PetscInt o, PetscInt s) {
500:   return (o < 0 ? 2-(o+s) : 3+s-o)%3;
501: }

503: /* Return quad edge for orientation o, if it is r for o == 0 */
504: PETSC_STATIC_INLINE PetscInt GetQuadEdge_Static(PetscInt o, PetscInt r) {
505:   return (o < 0 ? 3-(o+r) : o+r)%4;
506: }
507: PETSC_STATIC_INLINE PetscInt GetQuadEdgeInverse_Static(PetscInt o, PetscInt s) {
508:   return (o < 0 ? 3-(o+s) : 4+s-o)%4;
509: }

511: /* Return quad subface for orientation o, if it is r for o == 0 */
512: PETSC_STATIC_INLINE PetscInt GetQuadSubface_Static(PetscInt o, PetscInt r) {
513:   return (o < 0 ? 4-(o+r) : o+r)%4;
514: }
515: PETSC_STATIC_INLINE PetscInt GetQuadSubfaceInverse_Static(PetscInt o, PetscInt s) {
516:   return (o < 0 ? 4-(o+s) : 4+s-o)%4;
517: }

519: static PetscErrorCode DMLabelSetStratumBounds(DMLabel label, PetscInt value, PetscInt cStart, PetscInt cEnd)
520: {
521:   IS             cIS;

525:   ISCreateStride(PETSC_COMM_SELF, cEnd - cStart, cStart, 1, &cIS);
526:   DMLabelSetStratumIS(label, value, cIS);
527:   ISDestroy(&cIS);
528:   return(0);
529: }

531: static PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
532: {
533:   PetscInt       depth, cStart, cStartNew, cEnd, cEndNew, cMax, c, vStart, vStartNew, vEnd, vEndNew, vMax, v, fStart, fStartNew, fEnd, fEndNew, fMax, f, eStart, eStartNew, eEnd, eEndNew, eMax, e, r;
534:   DMLabel        depthLabel;

538:   DMPlexGetDepth(dm, &depth);
539:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
540:   DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
541:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
542:   DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
543:   DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
544:   GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);
545:   GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);
546:   DMCreateLabel(rdm,"depth");
547:   DMPlexGetDepthLabel(rdm,&depthLabel);
548:   DMLabelSetStratumBounds(depthLabel, 0, vStartNew, vEndNew);
549:   if (depth > 2) DMLabelSetStratumBounds(depthLabel, 1, eStartNew, eEndNew);
550:   if (depth > 1) DMLabelSetStratumBounds(depthLabel, depth - 1, fStartNew, fEndNew);
551:   if (depth > 0) DMLabelSetStratumBounds(depthLabel, depth, cStartNew, cEndNew);
552:   {
553:     DM_Plex *plex = (DM_Plex *) rdm->data;
554:     PetscObjectStateGet((PetscObject) depthLabel, &plex->depthState);
555:   }
556:   if (!refiner) return(0);
557:   switch (refiner) {
558:   case REFINER_SIMPLEX_1D:
559:     /* All cells have 2 vertices */
560:     for (c = cStart; c < cEnd; ++c) {
561:       for (r = 0; r < 2; ++r) {
562:         const PetscInt newp = cStartNew + (c - cStart)*2 + r;

564:         DMPlexSetConeSize(rdm, newp, 2);
565:       }
566:     }
567:     /* Old vertices have identical supports */
568:     for (v = vStart; v < vEnd; ++v) {
569:       const PetscInt newp = vStartNew + (v - vStart);
570:       PetscInt       size;

572:       DMPlexGetSupportSize(dm, v, &size);
573:       DMPlexSetSupportSize(rdm, newp, size);
574:     }
575:     /* Cell vertices have support 2 */
576:     for (c = cStart; c < cEnd; ++c) {
577:       const PetscInt newp = vStartNew + (vEnd - vStart) + (c - cStart);

579:       DMPlexSetSupportSize(rdm, newp, 2);
580:     }
581:     break;
582:   case REFINER_SIMPLEX_2D:
583:     /* All cells have 3 faces */
584:     for (c = cStart; c < cEnd; ++c) {
585:       for (r = 0; r < 4; ++r) {
586:         const PetscInt newp = (c - cStart)*4 + r;

588:         DMPlexSetConeSize(rdm, newp, 3);
589:       }
590:     }
591:     /* Split faces have 2 vertices and the same cells as the parent */
592:     for (f = fStart; f < fEnd; ++f) {
593:       for (r = 0; r < 2; ++r) {
594:         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
595:         PetscInt       size;

597:         DMPlexSetConeSize(rdm, newp, 2);
598:         DMPlexGetSupportSize(dm, f, &size);
599:         DMPlexSetSupportSize(rdm, newp, size);
600:       }
601:     }
602:     /* Interior faces have 2 vertices and 2 cells */
603:     for (c = cStart; c < cEnd; ++c) {
604:       for (r = 0; r < 3; ++r) {
605:         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;

607:         DMPlexSetConeSize(rdm, newp, 2);
608:         DMPlexSetSupportSize(rdm, newp, 2);
609:       }
610:     }
611:     /* Old vertices have identical supports */
612:     for (v = vStart; v < vEnd; ++v) {
613:       const PetscInt newp = vStartNew + (v - vStart);
614:       PetscInt       size;

616:       DMPlexGetSupportSize(dm, v, &size);
617:       DMPlexSetSupportSize(rdm, newp, size);
618:     }
619:     /* Face vertices have 2 + cells*2 supports */
620:     for (f = fStart; f < fEnd; ++f) {
621:       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
622:       PetscInt       size;

624:       DMPlexGetSupportSize(dm, f, &size);
625:       DMPlexSetSupportSize(rdm, newp, 2 + size*2);
626:     }
627:     break;
628:   case REFINER_SIMPLEX_TO_HEX_2D:
629:     /* All cells have 4 faces */
630:     for (c = cStart; c < cEnd; ++c) {
631:       for (r = 0; r < 3; ++r) {
632:         const PetscInt newp = (c - cStart)*3 + r;

634:         DMPlexSetConeSize(rdm, newp, 4);
635:       }
636:     }
637:     /* Split faces have 2 vertices and the same cells as the parent */
638:     for (f = fStart; f < fEnd; ++f) {
639:       for (r = 0; r < 2; ++r) {
640:         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
641:         PetscInt       size;

643:         DMPlexSetConeSize(rdm, newp, 2);
644:         DMPlexGetSupportSize(dm, f, &size);
645:         DMPlexSetSupportSize(rdm, newp, size);
646:       }
647:     }
648:     /* Interior faces have 2 vertices and 2 cells */
649:     for (c = cStart; c < cEnd; ++c) {
650:       for (r = 0; r < 3; ++r) {
651:         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;

653:         DMPlexSetConeSize(rdm, newp, 2);
654:         DMPlexSetSupportSize(rdm, newp, 2);
655:       }
656:     }
657:     /* Old vertices have identical supports */
658:     for (v = vStart; v < vEnd; ++v) {
659:       const PetscInt newp = vStartNew + (v - vStart);
660:       PetscInt       size;

662:       DMPlexGetSupportSize(dm, v, &size);
663:       DMPlexSetSupportSize(rdm, newp, size);
664:     }
665:     /* Split-face vertices have cells + 2 supports */
666:     for (f = fStart; f < fEnd; ++f) {
667:       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
668:       PetscInt       size;

670:       DMPlexGetSupportSize(dm, f, &size);
671:       DMPlexSetSupportSize(rdm, newp, size + 2);
672:     }
673:     /* Interior vertices have 3 supports */
674:     for (c = cStart; c < cEnd; ++c) {
675:       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;

677:       DMPlexSetSupportSize(rdm, newp, 3);
678:     }
679:     break;
680:   case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
681:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
682:     /* the mesh is no longer hybrid */
683:     cMax = PetscMin(cEnd, cMax);
684:     /* All cells have 4 faces */
685:     for (c = cStart; c < cMax; ++c) {
686:       for (r = 0; r < 3; ++r) {
687:         const PetscInt newp = (c - cStart)*3 + r;

689:         DMPlexSetConeSize(rdm, newp, 4);
690:       }
691:     }
692:     for (c = cMax; c < cEnd; ++c) {
693:       for (r = 0; r < 4; ++r) {
694:         const PetscInt newp = (cMax - cStart)*3 + (c - cMax)*4 + r;

696:         DMPlexSetConeSize(rdm, newp, 4);
697:       }
698:     }
699:     /* Split faces have 2 vertices and the same cells as the parent */
700:     for (f = fStart; f < fEnd; ++f) {
701:       for (r = 0; r < 2; ++r) {
702:         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
703:         PetscInt       size;

705:         DMPlexSetConeSize(rdm, newp, 2);
706:         DMPlexGetSupportSize(dm, f, &size);
707:         DMPlexSetSupportSize(rdm, newp, size);
708:       }
709:     }
710:     /* Interior faces have 2 vertices and 2 cells */
711:     for (c = cStart; c < cMax; ++c) {
712:       for (r = 0; r < 3; ++r) {
713:         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;

715:         DMPlexSetConeSize(rdm, newp, 2);
716:         DMPlexSetSupportSize(rdm, newp, 2);
717:       }
718:     }
719:     /* Hybrid interior faces have 2 vertices and 2 cells */
720:     for (c = cMax; c < cEnd; ++c) {
721:       for (r = 0; r < 4; ++r) {
722:         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (c - cMax)*4 + r;

724:         DMPlexSetConeSize(rdm, newp, 2);
725:         DMPlexSetSupportSize(rdm, newp, 2);
726:       }
727:     }
728:     /* Old vertices have identical supports */
729:     for (v = vStart; v < vEnd; ++v) {
730:       const PetscInt newp = vStartNew + (v - vStart);
731:       PetscInt       size;

733:       DMPlexGetSupportSize(dm, v, &size);
734:       DMPlexSetSupportSize(rdm, newp, size);
735:     }
736:     /* Split-face vertices have cells + 2 supports */
737:     for (f = fStart; f < fEnd; ++f) {
738:       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
739:       PetscInt       size;

741:       DMPlexGetSupportSize(dm, f, &size);
742:       DMPlexSetSupportSize(rdm, newp, size + 2);
743:     }
744:     /* Interior vertices have 3 supports */
745:     for (c = cStart; c < cMax; ++c) {
746:       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;

748:       DMPlexSetSupportSize(rdm, newp, 3);
749:     }
750:     /* Hybrid interior vertices have 4 supports */
751:     for (c = cMax; c < cEnd; ++c) {
752:       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;

754:       DMPlexSetSupportSize(rdm, newp, 4);
755:     }
756:     break;
757:   case REFINER_HEX_2D:
758:     /* All cells have 4 faces */
759:     for (c = cStart; c < cEnd; ++c) {
760:       for (r = 0; r < 4; ++r) {
761:         const PetscInt newp = cStartNew + (c - cStart)*4 + r;

763:         DMPlexSetConeSize(rdm, newp, 4);
764:       }
765:     }
766:     /* Split faces have 2 vertices and the same cells as the parent */
767:     for (f = fStart; f < fEnd; ++f) {
768:       for (r = 0; r < 2; ++r) {
769:         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
770:         PetscInt       size;

772:         DMPlexSetConeSize(rdm, newp, 2);
773:         DMPlexGetSupportSize(dm, f, &size);
774:         DMPlexSetSupportSize(rdm, newp, size);
775:       }
776:     }
777:     /* Interior faces have 2 vertices and 2 cells */
778:     for (c = cStart; c < cEnd; ++c) {
779:       for (r = 0; r < 4; ++r) {
780:         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;

782:         DMPlexSetConeSize(rdm, newp, 2);
783:         DMPlexSetSupportSize(rdm, newp, 2);
784:       }
785:     }
786:     /* Old vertices have identical supports */
787:     for (v = vStart; v < vEnd; ++v) {
788:       const PetscInt newp = vStartNew + (v - vStart);
789:       PetscInt       size;

791:       DMPlexGetSupportSize(dm, v, &size);
792:       DMPlexSetSupportSize(rdm, newp, size);
793:     }
794:     /* Face vertices have 2 + cells supports */
795:     for (f = fStart; f < fEnd; ++f) {
796:       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
797:       PetscInt       size;

799:       DMPlexGetSupportSize(dm, f, &size);
800:       DMPlexSetSupportSize(rdm, newp, 2 + size);
801:     }
802:     /* Cell vertices have 4 supports */
803:     for (c = cStart; c < cEnd; ++c) {
804:       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);

806:       DMPlexSetSupportSize(rdm, newp, 4);
807:     }
808:     break;
809:   case REFINER_HYBRID_SIMPLEX_2D:
810:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
811:     cMax = PetscMin(cEnd, cMax);
812:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
813:     fMax = PetscMin(fEnd, fMax);
814:     DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);
815:     /* Interior cells have 3 faces */
816:     for (c = cStart; c < cMax; ++c) {
817:       for (r = 0; r < 4; ++r) {
818:         const PetscInt newp = cStartNew + (c - cStart)*4 + r;

820:         DMPlexSetConeSize(rdm, newp, 3);
821:       }
822:     }
823:     /* Hybrid cells have 4 faces */
824:     for (c = cMax; c < cEnd; ++c) {
825:       for (r = 0; r < 2; ++r) {
826:         const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;

828:         DMPlexSetConeSize(rdm, newp, 4);
829:       }
830:     }
831:     /* Interior split faces have 2 vertices and the same cells as the parent */
832:     for (f = fStart; f < fMax; ++f) {
833:       for (r = 0; r < 2; ++r) {
834:         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
835:         PetscInt       size;

837:         DMPlexSetConeSize(rdm, newp, 2);
838:         DMPlexGetSupportSize(dm, f, &size);
839:         DMPlexSetSupportSize(rdm, newp, size);
840:       }
841:     }
842:     /* Interior cell faces have 2 vertices and 2 cells */
843:     for (c = cStart; c < cMax; ++c) {
844:       for (r = 0; r < 3; ++r) {
845:         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;

847:         DMPlexSetConeSize(rdm, newp, 2);
848:         DMPlexSetSupportSize(rdm, newp, 2);
849:       }
850:     }
851:     /* Hybrid faces have 2 vertices and the same cells */
852:     for (f = fMax; f < fEnd; ++f) {
853:       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
854:       PetscInt       size;

856:       DMPlexSetConeSize(rdm, newp, 2);
857:       DMPlexGetSupportSize(dm, f, &size);
858:       DMPlexSetSupportSize(rdm, newp, size);
859:     }
860:     /* Hybrid cell faces have 2 vertices and 2 cells */
861:     for (c = cMax; c < cEnd; ++c) {
862:       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);

864:       DMPlexSetConeSize(rdm, newp, 2);
865:       DMPlexSetSupportSize(rdm, newp, 2);
866:     }
867:     /* Old vertices have identical supports */
868:     for (v = vStart; v < vEnd; ++v) {
869:       const PetscInt newp = vStartNew + (v - vStart);
870:       PetscInt       size;

872:       DMPlexGetSupportSize(dm, v, &size);
873:       DMPlexSetSupportSize(rdm, newp, size);
874:     }
875:     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
876:     for (f = fStart; f < fMax; ++f) {
877:       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
878:       const PetscInt *support;
879:       PetscInt       size, newSize = 2, s;

881:       DMPlexGetSupportSize(dm, f, &size);
882:       DMPlexGetSupport(dm, f, &support);
883:       for (s = 0; s < size; ++s) {
884:         if (support[s] >= cMax) newSize += 1;
885:         else newSize += 2;
886:       }
887:       DMPlexSetSupportSize(rdm, newp, newSize);
888:     }
889:     break;
890:   case REFINER_HYBRID_HEX_2D:
891:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
892:     cMax = PetscMin(cEnd, cMax);
893:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
894:     fMax = PetscMin(fEnd, fMax);
895:     DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4, PETSC_DETERMINE, PETSC_DETERMINE);
896:     /* Interior cells have 4 faces */
897:     for (c = cStart; c < cMax; ++c) {
898:       for (r = 0; r < 4; ++r) {
899:         const PetscInt newp = cStartNew + (c - cStart)*4 + r;

901:         DMPlexSetConeSize(rdm, newp, 4);
902:       }
903:     }
904:     /* Hybrid cells have 4 faces */
905:     for (c = cMax; c < cEnd; ++c) {
906:       for (r = 0; r < 2; ++r) {
907:         const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;

909:         DMPlexSetConeSize(rdm, newp, 4);
910:       }
911:     }
912:     /* Interior split faces have 2 vertices and the same cells as the parent */
913:     for (f = fStart; f < fMax; ++f) {
914:       for (r = 0; r < 2; ++r) {
915:         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
916:         PetscInt       size;

918:         DMPlexSetConeSize(rdm, newp, 2);
919:         DMPlexGetSupportSize(dm, f, &size);
920:         DMPlexSetSupportSize(rdm, newp, size);
921:       }
922:     }
923:     /* Interior cell faces have 2 vertices and 2 cells */
924:     for (c = cStart; c < cMax; ++c) {
925:       for (r = 0; r < 4; ++r) {
926:         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;

928:         DMPlexSetConeSize(rdm, newp, 2);
929:         DMPlexSetSupportSize(rdm, newp, 2);
930:       }
931:     }
932:     /* Hybrid faces have 2 vertices and the same cells */
933:     for (f = fMax; f < fEnd; ++f) {
934:       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (f - fMax);
935:       PetscInt       size;

937:       DMPlexSetConeSize(rdm, newp, 2);
938:       DMPlexGetSupportSize(dm, f, &size);
939:       DMPlexSetSupportSize(rdm, newp, size);
940:     }
941:     /* Hybrid cell faces have 2 vertices and 2 cells */
942:     for (c = cMax; c < cEnd; ++c) {
943:       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);

945:       DMPlexSetConeSize(rdm, newp, 2);
946:       DMPlexSetSupportSize(rdm, newp, 2);
947:     }
948:     /* Old vertices have identical supports */
949:     for (v = vStart; v < vEnd; ++v) {
950:       const PetscInt newp = vStartNew + (v - vStart);
951:       PetscInt       size;

953:       DMPlexGetSupportSize(dm, v, &size);
954:       DMPlexSetSupportSize(rdm, newp, size);
955:     }
956:     /* Face vertices have 2 + cells supports */
957:     for (f = fStart; f < fMax; ++f) {
958:       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
959:       PetscInt       size;

961:       DMPlexGetSupportSize(dm, f, &size);
962:       DMPlexSetSupportSize(rdm, newp, 2 + size);
963:     }
964:     /* Cell vertices have 4 supports */
965:     for (c = cStart; c < cMax; ++c) {
966:       const PetscInt newp = vStartNew + (vEnd - vStart) + (fMax - fStart) + (c - cStart);

968:       DMPlexSetSupportSize(rdm, newp, 4);
969:     }
970:     break;
971:   case REFINER_SIMPLEX_3D:
972:     /* All cells have 4 faces */
973:     for (c = cStart; c < cEnd; ++c) {
974:       for (r = 0; r < 8; ++r) {
975:         const PetscInt newp = cStartNew + (c - cStart)*8 + r;

977:         DMPlexSetConeSize(rdm, newp, 4);
978:       }
979:     }
980:     /* Split faces have 3 edges and the same cells as the parent */
981:     for (f = fStart; f < fEnd; ++f) {
982:       for (r = 0; r < 4; ++r) {
983:         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
984:         PetscInt       size;

986:         DMPlexSetConeSize(rdm, newp, 3);
987:         DMPlexGetSupportSize(dm, f, &size);
988:         DMPlexSetSupportSize(rdm, newp, size);
989:       }
990:     }
991:     /* Interior cell faces have 3 edges and 2 cells */
992:     for (c = cStart; c < cEnd; ++c) {
993:       for (r = 0; r < 8; ++r) {
994:         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + r;

996:         DMPlexSetConeSize(rdm, newp, 3);
997:         DMPlexSetSupportSize(rdm, newp, 2);
998:       }
999:     }
1000:     /* Split edges have 2 vertices and the same faces */
1001:     for (e = eStart; e < eEnd; ++e) {
1002:       for (r = 0; r < 2; ++r) {
1003:         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1004:         PetscInt       size;

1006:         DMPlexSetConeSize(rdm, newp, 2);
1007:         DMPlexGetSupportSize(dm, e, &size);
1008:         DMPlexSetSupportSize(rdm, newp, size);
1009:       }
1010:     }
1011:     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
1012:     for (f = fStart; f < fEnd; ++f) {
1013:       for (r = 0; r < 3; ++r) {
1014:         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
1015:         const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
1016:         PetscInt        coneSize, c, supportSize, s, er, intFaces = 0;

1018:         DMPlexSetConeSize(rdm, newp, 2);
1019:         DMPlexGetSupportSize(dm, f, &supportSize);
1020:         DMPlexGetSupport(dm, f, &support);
1021:         for (s = 0; s < supportSize; ++s) {
1022:           DMPlexGetConeSize(dm, support[s], &coneSize);
1023:           DMPlexGetCone(dm, support[s], &cone);
1024:           DMPlexGetConeOrientation(dm, support[s], &ornt);
1025:           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
1026:           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
1027:           er = GetTriMidEdgeInverse_Static(ornt[c], r);
1028:           if (er == eint[c]) {
1029:             intFaces += 1;
1030:           } else {
1031:             intFaces += 2;
1032:           }
1033:         }
1034:         DMPlexSetSupportSize(rdm, newp, 2+intFaces);
1035:       }
1036:     }
1037:     /* Interior cell edges have 2 vertices and 4 faces */
1038:     for (c = cStart; c < cEnd; ++c) {
1039:       const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);

1041:       DMPlexSetConeSize(rdm, newp, 2);
1042:       DMPlexSetSupportSize(rdm, newp, 4);
1043:     }
1044:     /* Old vertices have identical supports */
1045:     for (v = vStart; v < vEnd; ++v) {
1046:       const PetscInt newp = vStartNew + (v - vStart);
1047:       PetscInt       size;

1049:       DMPlexGetSupportSize(dm, v, &size);
1050:       DMPlexSetSupportSize(rdm, newp, size);
1051:     }
1052:     /* Edge vertices have 2 + faces*2 + cells*0/1 supports */
1053:     for (e = eStart; e < eEnd; ++e) {
1054:       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1055:       PetscInt       size, *star = NULL, starSize, s, cellSize = 0;

1057:       DMPlexGetSupportSize(dm, e, &size);
1058:       DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
1059:       for (s = 0; s < starSize*2; s += 2) {
1060:         const PetscInt *cone, *ornt;
1061:         PetscInt        e01, e23;

1063:         if ((star[s] >= cStart) && (star[s] < cEnd)) {
1064:           /* Check edge 0-1 */
1065:           DMPlexGetCone(dm, star[s], &cone);
1066:           DMPlexGetConeOrientation(dm, star[s], &ornt);
1067:           DMPlexGetCone(dm, cone[0], &cone);
1068:           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
1069:           /* Check edge 2-3 */
1070:           DMPlexGetCone(dm, star[s], &cone);
1071:           DMPlexGetConeOrientation(dm, star[s], &ornt);
1072:           DMPlexGetCone(dm, cone[2], &cone);
1073:           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
1074:           if ((e01 == e) || (e23 == e)) ++cellSize;
1075:         }
1076:       }
1077:       DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
1078:       DMPlexSetSupportSize(rdm, newp, 2 + size*2 + cellSize);
1079:     }
1080:     break;
1081:   case REFINER_HYBRID_SIMPLEX_3D:
1082:     DMPlexSetHybridBounds(rdm, cStartNew + 8*(cMax-cStart), fStartNew + 4*(fMax - fStart) + 8*(cMax - cStart),
1083:                                  eStartNew + 2*(eMax - eStart) + 3*(fMax - fStart) + (cMax - cStart), PETSC_DETERMINE);
1084:     /* Interior cells have 4 faces */
1085:     for (c = cStart; c < cMax; ++c) {
1086:       for (r = 0; r < 8; ++r) {
1087:         const PetscInt newp = cStartNew + (c - cStart)*8 + r;

1089:         DMPlexSetConeSize(rdm, newp, 4);
1090:       }
1091:     }
1092:     /* Hybrid cells have 5 faces */
1093:     for (c = cMax; c < cEnd; ++c) {
1094:       for (r = 0; r < 4; ++r) {
1095:         const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;

1097:         DMPlexSetConeSize(rdm, newp, 5);
1098:       }
1099:     }
1100:     /* Interior split faces have 3 edges and the same cells as the parent */
1101:     for (f = fStart; f < fMax; ++f) {
1102:       for (r = 0; r < 4; ++r) {
1103:         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
1104:         PetscInt       size;

1106:         DMPlexSetConeSize(rdm, newp, 3);
1107:         DMPlexGetSupportSize(dm, f, &size);
1108:         DMPlexSetSupportSize(rdm, newp, size);
1109:       }
1110:     }
1111:     /* Interior cell faces have 3 edges and 2 cells */
1112:     for (c = cStart; c < cMax; ++c) {
1113:       for (r = 0; r < 8; ++r) {
1114:         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + r;

1116:         DMPlexSetConeSize(rdm, newp, 3);
1117:         DMPlexSetSupportSize(rdm, newp, 2);
1118:       }
1119:     }
1120:     /* Hybrid split faces have 4 edges and the same cells as the parent */
1121:     for (f = fMax; f < fEnd; ++f) {
1122:       for (r = 0; r < 2; ++r) {
1123:         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;
1124:         PetscInt       size;

1126:         DMPlexSetConeSize(rdm, newp, 4);
1127:         DMPlexGetSupportSize(dm, f, &size);
1128:         DMPlexSetSupportSize(rdm, newp, size);
1129:       }
1130:     }
1131:     /* Hybrid cells faces have 4 edges and 2 cells */
1132:     for (c = cMax; c < cEnd; ++c) {
1133:       for (r = 0; r < 3; ++r) {
1134:         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + r;

1136:         DMPlexSetConeSize(rdm, newp, 4);
1137:         DMPlexSetSupportSize(rdm, newp, 2);
1138:       }
1139:     }
1140:     /* Interior split edges have 2 vertices and the same faces */
1141:     for (e = eStart; e < eMax; ++e) {
1142:       for (r = 0; r < 2; ++r) {
1143:         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1144:         PetscInt       size;

1146:         DMPlexSetConeSize(rdm, newp, 2);
1147:         DMPlexGetSupportSize(dm, e, &size);
1148:         DMPlexSetSupportSize(rdm, newp, size);
1149:       }
1150:     }
1151:     /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
1152:     for (f = fStart; f < fMax; ++f) {
1153:       for (r = 0; r < 3; ++r) {
1154:         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
1155:         const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
1156:         PetscInt        coneSize, c, supportSize, s, er, intFaces = 0;

1158:         DMPlexSetConeSize(rdm, newp, 2);
1159:         DMPlexGetSupportSize(dm, f, &supportSize);
1160:         DMPlexGetSupport(dm, f, &support);
1161:         for (s = 0; s < supportSize; ++s) {
1162:           DMPlexGetConeSize(dm, support[s], &coneSize);
1163:           DMPlexGetCone(dm, support[s], &cone);
1164:           DMPlexGetConeOrientation(dm, support[s], &ornt);
1165:           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
1166:           if (support[s] < cMax) {
1167:             /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
1168:             er = GetTriMidEdgeInverse_Static(ornt[c], r);
1169:             if (er == eint[c]) {
1170:               intFaces += 1;
1171:             } else {
1172:               intFaces += 2;
1173:             }
1174:           } else {
1175:             intFaces += 1;
1176:           }
1177:         }
1178:         DMPlexSetSupportSize(rdm, newp, 2+intFaces);
1179:       }
1180:     }
1181:     /* Interior cell edges have 2 vertices and 4 faces */
1182:     for (c = cStart; c < cMax; ++c) {
1183:       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);

1185:       DMPlexSetConeSize(rdm, newp, 2);
1186:       DMPlexSetSupportSize(rdm, newp, 4);
1187:     }
1188:     /* Hybrid edges have 2 vertices and the same faces */
1189:     for (e = eMax; e < eEnd; ++e) {
1190:       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
1191:       PetscInt       size;

1193:       DMPlexSetConeSize(rdm, newp, 2);
1194:       DMPlexGetSupportSize(dm, e, &size);
1195:       DMPlexSetSupportSize(rdm, newp, size);
1196:     }
1197:     /* Hybrid face edges have 2 vertices and 2+2*cells faces */
1198:     for (f = fMax; f < fEnd; ++f) {
1199:       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
1200:       PetscInt       size;

1202:       DMPlexSetConeSize(rdm, newp, 2);
1203:       DMPlexGetSupportSize(dm, f, &size);
1204:       DMPlexSetSupportSize(rdm, newp, 2+2*size);
1205:     }
1206:     /* Interior vertices have identical supports */
1207:     for (v = vStart; v < vEnd; ++v) {
1208:       const PetscInt newp = vStartNew + (v - vStart);
1209:       PetscInt       size;

1211:       DMPlexGetSupportSize(dm, v, &size);
1212:       DMPlexSetSupportSize(rdm, newp, size);
1213:     }
1214:     /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
1215:     for (e = eStart; e < eMax; ++e) {
1216:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
1217:       const PetscInt *support;
1218:       PetscInt        size, *star = NULL, starSize, s, faceSize = 0, cellSize = 0;

1220:       DMPlexGetSupportSize(dm, e, &size);
1221:       DMPlexGetSupport(dm, e, &support);
1222:       for (s = 0; s < size; ++s) {
1223:         if (support[s] < fMax) faceSize += 2;
1224:         else                   faceSize += 1;
1225:       }
1226:       DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
1227:       for (s = 0; s < starSize*2; s += 2) {
1228:         const PetscInt *cone, *ornt;
1229:         PetscInt        e01, e23;

1231:         if ((star[s] >= cStart) && (star[s] < cMax)) {
1232:           /* Check edge 0-1 */
1233:           DMPlexGetCone(dm, star[s], &cone);
1234:           DMPlexGetConeOrientation(dm, star[s], &ornt);
1235:           DMPlexGetCone(dm, cone[0], &cone);
1236:           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
1237:           /* Check edge 2-3 */
1238:           DMPlexGetCone(dm, star[s], &cone);
1239:           DMPlexGetConeOrientation(dm, star[s], &ornt);
1240:           DMPlexGetCone(dm, cone[2], &cone);
1241:           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
1242:           if ((e01 == e) || (e23 == e)) ++cellSize;
1243:         }
1244:       }
1245:       DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
1246:       DMPlexSetSupportSize(rdm, newp, 2 + faceSize + cellSize);
1247:     }
1248:     break;
1249:   case REFINER_SIMPLEX_TO_HEX_3D:
1250:     /* All cells have 6 faces */
1251:     for (c = cStart; c < cEnd; ++c) {
1252:       for (r = 0; r < 4; ++r) {
1253:         const PetscInt newp = cStartNew + (c - cStart)*4 + r;

1255:         DMPlexSetConeSize(rdm, newp, 6);
1256:       }
1257:     }
1258:     /* Split faces have 4 edges and the same cells as the parent */
1259:     for (f = fStart; f < fEnd; ++f) {
1260:       for (r = 0; r < 3; ++r) {
1261:         const PetscInt newp = fStartNew + (f - fStart)*3 + r;
1262:         PetscInt       size;

1264:         DMPlexSetConeSize(rdm, newp, 4);
1265:         DMPlexGetSupportSize(dm, f, &size);
1266:         DMPlexSetSupportSize(rdm, newp, size);
1267:       }
1268:     }
1269:     /* Interior cell faces have 4 edges and 2 cells */
1270:     for (c = cStart; c < cEnd; ++c) {
1271:       for (r = 0; r < 6; ++r) {
1272:         const PetscInt newp = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + r;

1274:         DMPlexSetConeSize(rdm, newp, 4);
1275:         DMPlexSetSupportSize(rdm, newp, 2);
1276:       }
1277:     }
1278:     /* Split edges have 2 vertices and the same faces */
1279:     for (e = eStart; e < eEnd; ++e) {
1280:       for (r = 0; r < 2; ++r) {
1281:         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1282:         PetscInt       size;

1284:         DMPlexSetConeSize(rdm, newp, 2);
1285:         DMPlexGetSupportSize(dm, e, &size);
1286:         DMPlexSetSupportSize(rdm, newp, size);
1287:       }
1288:     }
1289:     /* Face edges have 2 vertices and 2 + cell faces supports */
1290:     for (f = fStart; f < fEnd; ++f) {
1291:       for (r = 0; r < 3; ++r) {
1292:         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
1293:         PetscInt        size;

1295:         DMPlexSetConeSize(rdm, newp, 2);
1296:         DMPlexGetSupportSize(dm, f, &size);
1297:         DMPlexSetSupportSize(rdm, newp, 2+size);
1298:       }
1299:     }
1300:     /* Interior cell edges have 2 vertices and 3 faces */
1301:     for (c = cStart; c < cEnd; ++c) {
1302:       for (r = 0; r < 4; ++r) {
1303:         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + r;

1305:         DMPlexSetConeSize(rdm, newp, 2);
1306:         DMPlexSetSupportSize(rdm, newp, 3);
1307:       }
1308:     }
1309:     /* Old vertices have identical supports */
1310:     for (v = vStart; v < vEnd; ++v) {
1311:       const PetscInt newp = vStartNew + (v - vStart);
1312:       PetscInt       size;

1314:       DMPlexGetSupportSize(dm, v, &size);
1315:       DMPlexSetSupportSize(rdm, newp, size);
1316:     }
1317:     /* Edge vertices have 2 + faces supports */
1318:     for (e = eStart; e < eEnd; ++e) {
1319:       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1320:       PetscInt       size;

1322:       DMPlexGetSupportSize(dm, e, &size);
1323:       DMPlexSetSupportSize(rdm, newp, 2 + size);
1324:     }
1325:     /* Face vertices have 3 + cells supports */
1326:     for (f = fStart; f < fEnd; ++f) {
1327:       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + f - fStart;
1328:       PetscInt       size;

1330:       DMPlexGetSupportSize(dm, f, &size);
1331:       DMPlexSetSupportSize(rdm, newp, 3 + size);
1332:     }
1333:     /* Interior cell vertices have 4 supports */
1334:     for (c = cStart; c < cEnd; ++c) {
1335:       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + fEnd - fStart + c - cStart;

1337:       DMPlexSetSupportSize(rdm, newp, 4);
1338:     }
1339:     break;
1340:   case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
1341:     /* the mesh is no longer hybrid */
1342:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
1343:     cMax = PetscMin(cEnd, cMax);
1344:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
1345:     fMax = PetscMin(fEnd, fMax);
1346:     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
1347:     eMax = PetscMin(eEnd, eMax);
1348:     /* All cells have 6 faces */
1349:     for (c = cStart; c < cMax; ++c) {
1350:       for (r = 0; r < 4; ++r) {
1351:         const PetscInt newp = cStartNew + (c - cStart)*4 + r;

1353:         DMPlexSetConeSize(rdm, newp, 6);
1354:       }
1355:     }
1356:     for (c = cMax; c < cEnd; ++c) {
1357:       for (r = 0; r < 3; ++r) {
1358:         const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + r;

1360:         DMPlexSetConeSize(rdm, newp, 6);
1361:       }
1362:     }
1363:     /* Interior split faces have 4 edges and the same cells as the parent */
1364:     for (f = fStart; f < fMax; ++f) {
1365:       for (r = 0; r < 3; ++r) {
1366:         const PetscInt newp = fStartNew + (f - fStart)*3 + r;
1367:         PetscInt       size;

1369:         DMPlexSetConeSize(rdm, newp, 4);
1370:         DMPlexGetSupportSize(dm, f, &size);
1371:         DMPlexSetSupportSize(rdm, newp, size);
1372:       }
1373:     }
1374:     /* Interior cell faces have 4 edges and 2 cells */
1375:     for (c = cStart; c < cMax; ++c) {
1376:       for (r = 0; r < 6; ++r) {
1377:         const PetscInt newp = fStartNew + (fMax - fStart)*3 + (c - cStart)*6 + r;

1379:         DMPlexSetConeSize(rdm, newp, 4);
1380:         DMPlexSetSupportSize(rdm, newp, 2);
1381:       }
1382:     }
1383:     /* Hybrid split faces have 4 edges and the same cells as the parent */
1384:     for (f = fMax; f < fEnd; ++f) {
1385:       for (r = 0; r < 2; ++r) {
1386:         const PetscInt newp = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (f - fMax)*2 + r;
1387:         PetscInt       size;

1389:         DMPlexSetConeSize(rdm, newp, 4);
1390:         DMPlexGetSupportSize(dm, f, &size);
1391:         DMPlexSetSupportSize(rdm, newp, size);
1392:       }
1393:     }
1394:     /* Hybrid cell faces have 4 edges and 2 cells */
1395:     for (c = cMax; c < cEnd; ++c) {
1396:       for (r = 0; r < 3; ++r) {
1397:         const PetscInt newp = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + r;

1399:         DMPlexSetConeSize(rdm, newp, 4);
1400:         DMPlexSetSupportSize(rdm, newp, 2);
1401:       }
1402:     }
1403:     /* Interior split edges have 2 vertices and the same faces */
1404:     for (e = eStart; e < eMax; ++e) {
1405:       for (r = 0; r < 2; ++r) {
1406:         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1407:         PetscInt       size;

1409:         DMPlexSetConeSize(rdm, newp, 2);
1410:         DMPlexGetSupportSize(dm, e, &size);
1411:         DMPlexSetSupportSize(rdm, newp, size);
1412:       }
1413:     }
1414:     /* Interior face edges have 2 vertices and 2 + cell faces supports */
1415:     for (f = fStart; f < fMax; ++f) {
1416:       for (r = 0; r < 3; ++r) {
1417:         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
1418:         PetscInt        size;

1420:         DMPlexSetConeSize(rdm, newp, 2);
1421:         DMPlexGetSupportSize(dm, f, &size);
1422:         DMPlexSetSupportSize(rdm, newp, 2+size);
1423:       }
1424:     }
1425:     /* Interior cell edges have 2 vertices and 3 faces */
1426:     for (c = cStart; c < cMax; ++c) {
1427:       for (r = 0; r < 4; ++r) {
1428:         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + r;

1430:         DMPlexSetConeSize(rdm, newp, 2);
1431:         DMPlexSetSupportSize(rdm, newp, 3);
1432:       }
1433:     }
1434:     /* Hybrid edges have 2 vertices and the same faces */
1435:     for (e = eMax; e < eEnd; ++e) {
1436:       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (e - eMax);
1437:       PetscInt       size;

1439:       DMPlexSetConeSize(rdm, newp, 2);
1440:       DMPlexGetSupportSize(dm, e, &size);
1441:       DMPlexSetSupportSize(rdm, newp, size);
1442:     }
1443:     /* Hybrid face edges have 2 vertices and 2+cells faces */
1444:     for (f = fMax; f < fEnd; ++f) {
1445:       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (f - fMax);
1446:       PetscInt        size;

1448:       DMPlexSetConeSize(rdm, newp, 2);
1449:       DMPlexGetSupportSize(dm, f, &size);
1450:       DMPlexSetSupportSize(rdm, newp, 2+size);
1451:     }
1452:     /* Hybrid cell edges have 2 vertices and 3 faces */
1453:     for (c = cMax; c < cEnd; ++c) {
1454:       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);

1456:       DMPlexSetConeSize(rdm, newp, 2);
1457:       DMPlexSetSupportSize(rdm, newp, 3);
1458:     }
1459:     /* Old vertices have identical supports */
1460:     for (v = vStart; v < vEnd; ++v) {
1461:       const PetscInt newp = vStartNew + (v - vStart);
1462:       PetscInt       size;

1464:       DMPlexGetSupportSize(dm, v, &size);
1465:       DMPlexSetSupportSize(rdm, newp, size);
1466:     }
1467:     /* Interior edge vertices have 2 + faces supports */
1468:     for (e = eStart; e < eMax; ++e) {
1469:       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1470:       PetscInt       size;

1472:       DMPlexGetSupportSize(dm, e, &size);
1473:       DMPlexSetSupportSize(rdm, newp, 2 + size);
1474:     }
1475:     /* Interior face vertices have 3 + cells supports */
1476:     for (f = fStart; f < fMax; ++f) {
1477:       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + f - fStart;
1478:       PetscInt       size;

1480:       DMPlexGetSupportSize(dm, f, &size);
1481:       DMPlexSetSupportSize(rdm, newp, 3 + size);
1482:     }
1483:     /* Interior cell vertices have 4 supports */
1484:     for (c = cStart; c < cMax; ++c) {
1485:       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + c - cStart;

1487:       DMPlexSetSupportSize(rdm, newp, 4);
1488:     }
1489:     break;
1490:   case REFINER_HEX_3D:
1491:     /* All cells have 6 faces */
1492:     for (c = cStart; c < cEnd; ++c) {
1493:       for (r = 0; r < 8; ++r) {
1494:         const PetscInt newp = (c - cStart)*8 + r;

1496:         DMPlexSetConeSize(rdm, newp, 6);
1497:       }
1498:     }
1499:     /* Split faces have 4 edges and the same cells as the parent */
1500:     for (f = fStart; f < fEnd; ++f) {
1501:       for (r = 0; r < 4; ++r) {
1502:         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
1503:         PetscInt       size;

1505:         DMPlexSetConeSize(rdm, newp, 4);
1506:         DMPlexGetSupportSize(dm, f, &size);
1507:         DMPlexSetSupportSize(rdm, newp, size);
1508:       }
1509:     }
1510:     /* Interior faces have 4 edges and 2 cells */
1511:     for (c = cStart; c < cEnd; ++c) {
1512:       for (r = 0; r < 12; ++r) {
1513:         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;

1515:         DMPlexSetConeSize(rdm, newp, 4);
1516:         DMPlexSetSupportSize(rdm, newp, 2);
1517:       }
1518:     }
1519:     /* Split edges have 2 vertices and the same faces as the parent */
1520:     for (e = eStart; e < eEnd; ++e) {
1521:       for (r = 0; r < 2; ++r) {
1522:         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1523:         PetscInt       size;

1525:         DMPlexSetConeSize(rdm, newp, 2);
1526:         DMPlexGetSupportSize(dm, e, &size);
1527:         DMPlexSetSupportSize(rdm, newp, size);
1528:       }
1529:     }
1530:     /* Face edges have 2 vertices and 2+cells faces */
1531:     for (f = fStart; f < fEnd; ++f) {
1532:       for (r = 0; r < 4; ++r) {
1533:         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
1534:         PetscInt       size;

1536:         DMPlexSetConeSize(rdm, newp, 2);
1537:         DMPlexGetSupportSize(dm, f, &size);
1538:         DMPlexSetSupportSize(rdm, newp, 2+size);
1539:       }
1540:     }
1541:     /* Cell edges have 2 vertices and 4 faces */
1542:     for (c = cStart; c < cEnd; ++c) {
1543:       for (r = 0; r < 6; ++r) {
1544:         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;

1546:         DMPlexSetConeSize(rdm, newp, 2);
1547:         DMPlexSetSupportSize(rdm, newp, 4);
1548:       }
1549:     }
1550:     /* Old vertices have identical supports */
1551:     for (v = vStart; v < vEnd; ++v) {
1552:       const PetscInt newp = vStartNew + (v - vStart);
1553:       PetscInt       size;

1555:       DMPlexGetSupportSize(dm, v, &size);
1556:       DMPlexSetSupportSize(rdm, newp, size);
1557:     }
1558:     /* Edge vertices have 2 + faces supports */
1559:     for (e = eStart; e < eEnd; ++e) {
1560:       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1561:       PetscInt       size;

1563:       DMPlexGetSupportSize(dm, e, &size);
1564:       DMPlexSetSupportSize(rdm, newp, 2 + size);
1565:     }
1566:     /* Face vertices have 4 + cells supports */
1567:     for (f = fStart; f < fEnd; ++f) {
1568:       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
1569:       PetscInt       size;

1571:       DMPlexGetSupportSize(dm, f, &size);
1572:       DMPlexSetSupportSize(rdm, newp, 4 + size);
1573:     }
1574:     /* Cell vertices have 6 supports */
1575:     for (c = cStart; c < cEnd; ++c) {
1576:       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);

1578:       DMPlexSetSupportSize(rdm, newp, 6);
1579:     }
1580:     break;
1581:   case REFINER_HYBRID_HEX_3D:
1582:     DMPlexSetHybridBounds(rdm, cStartNew + 8*(cMax-cStart), fStartNew + 4*(fMax - fStart) + 12*(cMax - cStart),
1583:                                  eStartNew + 2*(eMax - eStart) + 4*(fMax - fStart) + 6*(cMax - cStart), PETSC_DETERMINE);
1584:     /* Interior cells have 6 faces */
1585:     for (c = cStart; c < cMax; ++c) {
1586:       for (r = 0; r < 8; ++r) {
1587:         const PetscInt newp = cStartNew + (c - cStart)*8 + r;

1589:         DMPlexSetConeSize(rdm, newp, 6);
1590:       }
1591:     }
1592:     /* Hybrid cells have 6 faces */
1593:     for (c = cMax; c < cEnd; ++c) {
1594:       for (r = 0; r < 4; ++r) {
1595:         const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;

1597:         DMPlexSetConeSize(rdm, newp, 6);
1598:       }
1599:     }
1600:     /* Interior split faces have 4 edges and the same cells as the parent */
1601:     for (f = fStart; f < fMax; ++f) {
1602:       for (r = 0; r < 4; ++r) {
1603:         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
1604:         PetscInt       size;

1606:         DMPlexSetConeSize(rdm, newp, 4);
1607:         DMPlexGetSupportSize(dm, f, &size);
1608:         DMPlexSetSupportSize(rdm, newp, size);
1609:       }
1610:     }
1611:     /* Interior cell faces have 4 edges and 2 cells */
1612:     for (c = cStart; c < cMax; ++c) {
1613:       for (r = 0; r < 12; ++r) {
1614:         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + r;

1616:         DMPlexSetConeSize(rdm, newp, 4);
1617:         DMPlexSetSupportSize(rdm, newp, 2);
1618:       }
1619:     }
1620:     /* Hybrid split faces have 4 edges and the same cells as the parent */
1621:     for (f = fMax; f < fEnd; ++f) {
1622:       for (r = 0; r < 2; ++r) {
1623:         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + r;
1624:         PetscInt       size;

1626:         DMPlexSetConeSize(rdm, newp, 4);
1627:         DMPlexGetSupportSize(dm, f, &size);
1628:         DMPlexSetSupportSize(rdm, newp, size);
1629:       }
1630:     }
1631:     /* Hybrid cells faces have 4 edges and 2 cells */
1632:     for (c = cMax; c < cEnd; ++c) {
1633:       for (r = 0; r < 4; ++r) {
1634:         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + r;

1636:         DMPlexSetConeSize(rdm, newp, 4);
1637:         DMPlexSetSupportSize(rdm, newp, 2);
1638:       }
1639:     }
1640:     /* Interior split edges have 2 vertices and the same faces as the parent */
1641:     for (e = eStart; e < eMax; ++e) {
1642:       for (r = 0; r < 2; ++r) {
1643:         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1644:         PetscInt       size;

1646:         DMPlexSetConeSize(rdm, newp, 2);
1647:         DMPlexGetSupportSize(dm, e, &size);
1648:         DMPlexSetSupportSize(rdm, newp, size);
1649:       }
1650:     }
1651:     /* Interior face edges have 2 vertices and 2+cells faces */
1652:     for (f = fStart; f < fMax; ++f) {
1653:       for (r = 0; r < 4; ++r) {
1654:         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
1655:         PetscInt       size;

1657:         DMPlexSetConeSize(rdm, newp, 2);
1658:         DMPlexGetSupportSize(dm, f, &size);
1659:         DMPlexSetSupportSize(rdm, newp, 2+size);
1660:       }
1661:     }
1662:     /* Interior cell edges have 2 vertices and 4 faces */
1663:     for (c = cStart; c < cMax; ++c) {
1664:       for (r = 0; r < 6; ++r) {
1665:         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;

1667:         DMPlexSetConeSize(rdm, newp, 2);
1668:         DMPlexSetSupportSize(rdm, newp, 4);
1669:       }
1670:     }
1671:     /* Hybrid edges have 2 vertices and the same faces */
1672:     for (e = eMax; e < eEnd; ++e) {
1673:       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (e - eMax);
1674:       PetscInt       size;

1676:       DMPlexSetConeSize(rdm, newp, 2);
1677:       DMPlexGetSupportSize(dm, e, &size);
1678:       DMPlexSetSupportSize(rdm, newp, size);
1679:     }
1680:     /* Hybrid face edges have 2 vertices and 2+cells faces */
1681:     for (f = fMax; f < fEnd; ++f) {
1682:       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
1683:       PetscInt       size;

1685:       DMPlexSetConeSize(rdm, newp, 2);
1686:       DMPlexGetSupportSize(dm, f, &size);
1687:       DMPlexSetSupportSize(rdm, newp, 2+size);
1688:     }
1689:     /* Hybrid cell edges have 2 vertices and 4 faces */
1690:     for (c = cMax; c < cEnd; ++c) {
1691:       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);

1693:       DMPlexSetConeSize(rdm, newp, 2);
1694:       DMPlexSetSupportSize(rdm, newp, 4);
1695:     }
1696:     /* Interior vertices have identical supports */
1697:     for (v = vStart; v < vEnd; ++v) {
1698:       const PetscInt newp = vStartNew + (v - vStart);
1699:       PetscInt       size;

1701:       DMPlexGetSupportSize(dm, v, &size);
1702:       DMPlexSetSupportSize(rdm, newp, size);
1703:     }
1704:     /* Interior edge vertices have 2 + faces supports */
1705:     for (e = eStart; e < eMax; ++e) {
1706:       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1707:       PetscInt       size;

1709:       DMPlexGetSupportSize(dm, e, &size);
1710:       DMPlexSetSupportSize(rdm, newp, 2 + size);
1711:     }
1712:     /* Interior face vertices have 4 + cells supports */
1713:     for (f = fStart; f < fMax; ++f) {
1714:       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
1715:       PetscInt       size;

1717:       DMPlexGetSupportSize(dm, f, &size);
1718:       DMPlexSetSupportSize(rdm, newp, 4 + size);
1719:     }
1720:     /* Interior cell vertices have 6 supports */
1721:     for (c = cStart; c < cMax; ++c) {
1722:       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);

1724:       DMPlexSetSupportSize(rdm, newp, 6);
1725:     }
1726:     break;
1727:   default:
1728:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
1729:   }
1730:   return(0);
1731: }

1733: static PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
1734: {
1735:   const PetscInt *faces, cellInd[4] = {0, 1, 2, 3};
1736:   PetscInt        cStart,    cEnd,    cMax,    vStart,    vEnd, vMax, fStart,    fEnd,    fMax,    eStart,    eEnd,    eMax;
1737:   PetscInt        cStartNew, cEndNew, cMaxNew, vStartNew, vEndNew,    fStartNew, fEndNew, fMaxNew, eStartNew, eEndNew, eMaxNew;
1738:   PetscInt        depth, maxSupportSize, *supportRef, c, f, e, v, r;
1739: #if defined(PETSC_USE_DEBUG)
1740:   PetscInt        p;
1741: #endif
1742:   PetscErrorCode  ierr;

1745:   if (!refiner) return(0);
1746:   DMPlexGetDepth(dm, &depth);
1747:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
1748:   DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
1749:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
1750:   DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
1751:   DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
1752:   GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);
1753:   GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);
1754:   switch (refiner) {
1755:   case REFINER_SIMPLEX_1D:
1756:     /* Max support size of refined mesh is 2 */
1757:     PetscMalloc1(2, &supportRef);
1758:     /* All cells have 2 vertices */
1759:     for (c = cStart; c < cEnd; ++c) {
1760:       const PetscInt  newv = vStartNew + (vEnd - vStart) + (c - cStart);

1762:       for (r = 0; r < 2; ++r) {
1763:         const PetscInt newp = cStartNew + (c - cStart)*2 + r;
1764:         const PetscInt *cone;
1765:         PetscInt        coneNew[2];

1767:         DMPlexGetCone(dm, c, &cone);
1768:         coneNew[0]       = vStartNew + (cone[0] - vStart);
1769:         coneNew[1]       = vStartNew + (cone[1] - vStart);
1770:         coneNew[(r+1)%2] = newv;
1771:         DMPlexSetCone(rdm, newp, coneNew);
1772: #if defined(PETSC_USE_DEBUG)
1773:         if ((newp < cStartNew) || (newp >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp, cStartNew, cEndNew);
1774:         for (p = 0; p < 2; ++p) {
1775:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
1776:         }
1777: #endif
1778:       }
1779:     }
1780:     /* Old vertices have identical supports */
1781:     for (v = vStart; v < vEnd; ++v) {
1782:       const PetscInt  newp = vStartNew + (v - vStart);
1783:       const PetscInt *support, *cone;
1784:       PetscInt        size, s;

1786:       DMPlexGetSupportSize(dm, v, &size);
1787:       DMPlexGetSupport(dm, v, &support);
1788:       for (s = 0; s < size; ++s) {
1789:         PetscInt r = 0;

1791:         DMPlexGetCone(dm, support[s], &cone);
1792:         if (cone[1] == v) r = 1;
1793:         supportRef[s] = cStartNew + (support[s] - cStart)*2 + r;
1794:       }
1795:       DMPlexSetSupport(rdm, newp, supportRef);
1796: #if defined(PETSC_USE_DEBUG)
1797:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
1798:       for (p = 0; p < size; ++p) {
1799:         if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
1800:       }
1801: #endif
1802:     }
1803:     /* Cell vertices have support of 2 cells */
1804:     for (c = cStart; c < cEnd; ++c) {
1805:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (c - cStart);

1807:       supportRef[0] = cStartNew + (c - cStart)*2 + 0;
1808:       supportRef[1] = cStartNew + (c - cStart)*2 + 1;
1809:       DMPlexSetSupport(rdm, newp, supportRef);
1810: #if defined(PETSC_USE_DEBUG)
1811:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
1812:       for (p = 0; p < 2; ++p) {
1813:         if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
1814:       }
1815: #endif
1816:     }
1817:     PetscFree(supportRef);
1818:     break;
1819:   case REFINER_SIMPLEX_2D:
1820:     /*
1821:      2
1822:      |\
1823:      | \
1824:      |  \
1825:      |   \
1826:      | C  \
1827:      |     \
1828:      |      \
1829:      2---1---1
1830:      |\  D  / \
1831:      | 2   0   \
1832:      |A \ /  B  \
1833:      0---0-------1
1834:      */
1835:     /* All cells have 3 faces */
1836:     for (c = cStart; c < cEnd; ++c) {
1837:       const PetscInt  newp = cStartNew + (c - cStart)*4;
1838:       const PetscInt *cone, *ornt;
1839:       PetscInt        coneNew[3], orntNew[3];

1841:       DMPlexGetCone(dm, c, &cone);
1842:       DMPlexGetConeOrientation(dm, c, &ornt);
1843:       /* A triangle */
1844:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1845:       orntNew[0] = ornt[0];
1846:       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
1847:       orntNew[1] = -2;
1848:       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1849:       orntNew[2] = ornt[2];
1850:       DMPlexSetCone(rdm, newp+0, coneNew);
1851:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1852: #if defined(PETSC_USE_DEBUG)
1853:       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
1854:       for (p = 0; p < 3; ++p) {
1855:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
1856:       }
1857: #endif
1858:       /* B triangle */
1859:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1860:       orntNew[0] = ornt[0];
1861:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1862:       orntNew[1] = ornt[1];
1863:       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
1864:       orntNew[2] = -2;
1865:       DMPlexSetCone(rdm, newp+1, coneNew);
1866:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1867: #if defined(PETSC_USE_DEBUG)
1868:       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
1869:       for (p = 0; p < 3; ++p) {
1870:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
1871:       }
1872: #endif
1873:       /* C triangle */
1874:       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
1875:       orntNew[0] = -2;
1876:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1877:       orntNew[1] = ornt[1];
1878:       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1879:       orntNew[2] = ornt[2];
1880:       DMPlexSetCone(rdm, newp+2, coneNew);
1881:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
1882: #if defined(PETSC_USE_DEBUG)
1883:       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
1884:       for (p = 0; p < 3; ++p) {
1885:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
1886:       }
1887: #endif
1888:       /* D triangle */
1889:       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
1890:       orntNew[0] = 0;
1891:       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
1892:       orntNew[1] = 0;
1893:       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
1894:       orntNew[2] = 0;
1895:       DMPlexSetCone(rdm, newp+3, coneNew);
1896:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
1897: #if defined(PETSC_USE_DEBUG)
1898:       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
1899:       for (p = 0; p < 3; ++p) {
1900:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
1901:       }
1902: #endif
1903:     }
1904:     /* Split faces have 2 vertices and the same cells as the parent */
1905:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
1906:     PetscMalloc1(2 + maxSupportSize*2, &supportRef);
1907:     for (f = fStart; f < fEnd; ++f) {
1908:       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);

1910:       for (r = 0; r < 2; ++r) {
1911:         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
1912:         const PetscInt *cone, *ornt, *support;
1913:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

1915:         DMPlexGetCone(dm, f, &cone);
1916:         coneNew[0]       = vStartNew + (cone[0] - vStart);
1917:         coneNew[1]       = vStartNew + (cone[1] - vStart);
1918:         coneNew[(r+1)%2] = newv;
1919:         DMPlexSetCone(rdm, newp, coneNew);
1920: #if defined(PETSC_USE_DEBUG)
1921:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
1922:         for (p = 0; p < 2; ++p) {
1923:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
1924:         }
1925: #endif
1926:         DMPlexGetSupportSize(dm, f, &supportSize);
1927:         DMPlexGetSupport(dm, f, &support);
1928:         for (s = 0; s < supportSize; ++s) {
1929:           DMPlexGetConeSize(dm, support[s], &coneSize);
1930:           DMPlexGetCone(dm, support[s], &cone);
1931:           DMPlexGetConeOrientation(dm, support[s], &ornt);
1932:           for (c = 0; c < coneSize; ++c) {
1933:             if (cone[c] == f) break;
1934:           }
1935:           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
1936:         }
1937:         DMPlexSetSupport(rdm, newp, supportRef);
1938: #if defined(PETSC_USE_DEBUG)
1939:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
1940:         for (p = 0; p < supportSize; ++p) {
1941:           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
1942:         }
1943: #endif
1944:       }
1945:     }
1946:     /* Interior faces have 2 vertices and 2 cells */
1947:     for (c = cStart; c < cEnd; ++c) {
1948:       const PetscInt *cone;

1950:       DMPlexGetCone(dm, c, &cone);
1951:       for (r = 0; r < 3; ++r) {
1952:         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
1953:         PetscInt       coneNew[2];
1954:         PetscInt       supportNew[2];

1956:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
1957:         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
1958:         DMPlexSetCone(rdm, newp, coneNew);
1959: #if defined(PETSC_USE_DEBUG)
1960:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
1961:         for (p = 0; p < 2; ++p) {
1962:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
1963:         }
1964: #endif
1965:         supportNew[0] = (c - cStart)*4 + (r+1)%3;
1966:         supportNew[1] = (c - cStart)*4 + 3;
1967:         DMPlexSetSupport(rdm, newp, supportNew);
1968: #if defined(PETSC_USE_DEBUG)
1969:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
1970:         for (p = 0; p < 2; ++p) {
1971:           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
1972:         }
1973: #endif
1974:       }
1975:     }
1976:     /* Old vertices have identical supports */
1977:     for (v = vStart; v < vEnd; ++v) {
1978:       const PetscInt  newp = vStartNew + (v - vStart);
1979:       const PetscInt *support, *cone;
1980:       PetscInt        size, s;

1982:       DMPlexGetSupportSize(dm, v, &size);
1983:       DMPlexGetSupport(dm, v, &support);
1984:       for (s = 0; s < size; ++s) {
1985:         PetscInt r = 0;

1987:         DMPlexGetCone(dm, support[s], &cone);
1988:         if (cone[1] == v) r = 1;
1989:         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1990:       }
1991:       DMPlexSetSupport(rdm, newp, supportRef);
1992: #if defined(PETSC_USE_DEBUG)
1993:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
1994:       for (p = 0; p < size; ++p) {
1995:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
1996:       }
1997: #endif
1998:     }
1999:     /* Face vertices have 2 + cells*2 supports */
2000:     for (f = fStart; f < fEnd; ++f) {
2001:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
2002:       const PetscInt *cone, *support;
2003:       PetscInt        size, s;

2005:       DMPlexGetSupportSize(dm, f, &size);
2006:       DMPlexGetSupport(dm, f, &support);
2007:       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2008:       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2009:       for (s = 0; s < size; ++s) {
2010:         PetscInt r = 0;

2012:         DMPlexGetCone(dm, support[s], &cone);
2013:         if      (cone[1] == f) r = 1;
2014:         else if (cone[2] == f) r = 2;
2015:         supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
2016:         supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
2017:       }
2018:       DMPlexSetSupport(rdm, newp, supportRef);
2019: #if defined(PETSC_USE_DEBUG)
2020:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2021:       for (p = 0; p < 2+size*2; ++p) {
2022:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2023:       }
2024: #endif
2025:     }
2026:     PetscFree(supportRef);
2027:     break;
2028:   case REFINER_SIMPLEX_TO_HEX_2D:
2029:     /*
2030:      2
2031:      |\
2032:      | \
2033:      |  \
2034:      |   \
2035:      | C  \
2036:      |     \
2037:      2      1
2038:      |\    / \
2039:      | 2  1   \
2040:      |  \/     \
2041:      |   |      \
2042:      |A  |   B   \
2043:      |   0        \
2044:      |   |         \
2045:      0---0----------1
2046:      */
2047:     /* All cells have 4 faces */
2048:     for (c = cStart; c < cEnd; ++c) {
2049:       const PetscInt  newp = cStartNew + (c - cStart)*3;
2050:       const PetscInt *cone, *ornt;
2051:       PetscInt        coneNew[4], orntNew[4];

2053:       DMPlexGetCone(dm, c, &cone);
2054:       DMPlexGetConeOrientation(dm, c, &ornt);
2055:       /* A quad */
2056:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2057:       orntNew[0] = ornt[0];
2058:       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
2059:       orntNew[1] = 0;
2060:       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
2061:       orntNew[2] = -2;
2062:       coneNew[3] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2063:       orntNew[3] = ornt[2];
2064:       DMPlexSetCone(rdm, newp+0, coneNew);
2065:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2066: #if defined(PETSC_USE_DEBUG)
2067:       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
2068:       for (p = 0; p < 4; ++p) {
2069:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2070:       }
2071: #endif
2072:       /* B quad */
2073:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2074:       orntNew[0] = ornt[0];
2075:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2076:       orntNew[1] = ornt[1];
2077:       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
2078:       orntNew[2] = 0;
2079:       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
2080:       orntNew[3] = -2;
2081:       DMPlexSetCone(rdm, newp+1, coneNew);
2082:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2083: #if defined(PETSC_USE_DEBUG)
2084:       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
2085:       for (p = 0; p < 4; ++p) {
2086:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2087:       }
2088: #endif
2089:       /* C quad */
2090:       coneNew[0] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2091:       orntNew[0] = ornt[1];
2092:       coneNew[1] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2093:       orntNew[1] = ornt[2];
2094:       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
2095:       orntNew[2] = 0;
2096:       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
2097:       orntNew[3] = -2;
2098:       DMPlexSetCone(rdm, newp+2, coneNew);
2099:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2100: #if defined(PETSC_USE_DEBUG)
2101:       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
2102:       for (p = 0; p < 4; ++p) {
2103:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2104:       }
2105: #endif
2106:     }
2107:     /* Split faces have 2 vertices and the same cells as the parent */
2108:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
2109:     PetscMalloc1(2 + maxSupportSize*2, &supportRef);
2110:     for (f = fStart; f < fEnd; ++f) {
2111:       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);

2113:       for (r = 0; r < 2; ++r) {
2114:         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
2115:         const PetscInt *cone, *ornt, *support;
2116:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

2118:         DMPlexGetCone(dm, f, &cone);
2119:         coneNew[0]       = vStartNew + (cone[0] - vStart);
2120:         coneNew[1]       = vStartNew + (cone[1] - vStart);
2121:         coneNew[(r+1)%2] = newv;
2122:         DMPlexSetCone(rdm, newp, coneNew);
2123: #if defined(PETSC_USE_DEBUG)
2124:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2125:         for (p = 0; p < 2; ++p) {
2126:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2127:         }
2128: #endif
2129:         DMPlexGetSupportSize(dm, f, &supportSize);
2130:         DMPlexGetSupport(dm, f, &support);
2131:         for (s = 0; s < supportSize; ++s) {
2132:           DMPlexGetConeSize(dm, support[s], &coneSize);
2133:           DMPlexGetCone(dm, support[s], &cone);
2134:           DMPlexGetConeOrientation(dm, support[s], &ornt);
2135:           for (c = 0; c < coneSize; ++c) {
2136:             if (cone[c] == f) break;
2137:           }
2138:           supportRef[s] = cStartNew + (support[s] - cStart)*3 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
2139:         }
2140:         DMPlexSetSupport(rdm, newp, supportRef);
2141: #if defined(PETSC_USE_DEBUG)
2142:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2143:         for (p = 0; p < supportSize; ++p) {
2144:           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
2145:         }
2146: #endif
2147:       }
2148:     }
2149:     /* Interior faces have 2 vertices and 2 cells */
2150:     for (c = cStart; c < cEnd; ++c) {
2151:       const PetscInt *cone;

2153:       DMPlexGetCone(dm, c, &cone);
2154:       for (r = 0; r < 3; ++r) {
2155:         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
2156:         PetscInt       coneNew[2];
2157:         PetscInt       supportNew[2];

2159:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2160:         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
2161:         DMPlexSetCone(rdm, newp, coneNew);
2162: #if defined(PETSC_USE_DEBUG)
2163:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2164:         for (p = 0; p < 2; ++p) {
2165:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2166:         }
2167: #endif
2168:         supportNew[0] = (c - cStart)*3 + r%3;
2169:         supportNew[1] = (c - cStart)*3 + (r+1)%3;
2170:         DMPlexSetSupport(rdm, newp, supportNew);
2171: #if defined(PETSC_USE_DEBUG)
2172:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2173:         for (p = 0; p < 2; ++p) {
2174:           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
2175:         }
2176: #endif
2177:       }
2178:     }
2179:     /* Old vertices have identical supports */
2180:     for (v = vStart; v < vEnd; ++v) {
2181:       const PetscInt  newp = vStartNew + (v - vStart);
2182:       const PetscInt *support, *cone;
2183:       PetscInt        size, s;

2185:       DMPlexGetSupportSize(dm, v, &size);
2186:       DMPlexGetSupport(dm, v, &support);
2187:       for (s = 0; s < size; ++s) {
2188:         PetscInt r = 0;

2190:         DMPlexGetCone(dm, support[s], &cone);
2191:         if (cone[1] == v) r = 1;
2192:         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
2193:       }
2194:       DMPlexSetSupport(rdm, newp, supportRef);
2195: #if defined(PETSC_USE_DEBUG)
2196:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2197:       for (p = 0; p < size; ++p) {
2198:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2199:       }
2200: #endif
2201:     }
2202:     /* Split-face vertices have cells + 2 supports */
2203:     for (f = fStart; f < fEnd; ++f) {
2204:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
2205:       const PetscInt *cone, *support;
2206:       PetscInt        size, s;

2208:       DMPlexGetSupportSize(dm, f, &size);
2209:       DMPlexGetSupport(dm, f, &support);
2210:       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2211:       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2212:       for (s = 0; s < size; ++s) {
2213:         PetscInt r = 0;

2215:         DMPlexGetCone(dm, support[s], &cone);
2216:         if      (cone[1] == f) r = 1;
2217:         else if (cone[2] == f) r = 2;
2218:         supportRef[2+s+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
2219:       }
2220:       DMPlexSetSupport(rdm, newp, supportRef);
2221: #if defined(PETSC_USE_DEBUG)
2222:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2223:       for (p = 0; p < 2+size; ++p) {
2224:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2225:       }
2226: #endif
2227:     }
2228:     /* Interior vertices have 3 supports */
2229:     for (c = cStart; c < cEnd; ++c) {
2230:       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;

2232:       supportRef[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
2233:       supportRef[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
2234:       supportRef[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
2235:       DMPlexSetSupport(rdm, newp, supportRef);
2236:     }
2237:     PetscFree(supportRef);
2238:     break;
2239:   case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
2240:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
2241:     cMax = PetscMin(cEnd, cMax);
2242:     for (c = cStart; c < cMax; ++c) {
2243:       const PetscInt  newp = cStartNew + (c - cStart)*3;
2244:       const PetscInt *cone, *ornt;
2245:       PetscInt        coneNew[4], orntNew[4];

2247:       DMPlexGetCone(dm, c, &cone);
2248:       DMPlexGetConeOrientation(dm, c, &ornt);
2249:       /* A quad */
2250:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2251:       orntNew[0] = ornt[0];
2252:       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
2253:       orntNew[1] = 0;
2254:       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
2255:       orntNew[2] = -2;
2256:       coneNew[3] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2257:       orntNew[3] = ornt[2];
2258:       DMPlexSetCone(rdm, newp+0, coneNew);
2259:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2260: #if defined(PETSC_USE_DEBUG)
2261:       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
2262:       for (p = 0; p < 4; ++p) {
2263:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2264:       }
2265: #endif
2266:       /* B quad */
2267:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2268:       orntNew[0] = ornt[0];
2269:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2270:       orntNew[1] = ornt[1];
2271:       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
2272:       orntNew[2] = 0;
2273:       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
2274:       orntNew[3] = -2;
2275:       DMPlexSetCone(rdm, newp+1, coneNew);
2276:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2277: #if defined(PETSC_USE_DEBUG)
2278:       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
2279:       for (p = 0; p < 4; ++p) {
2280:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2281:       }
2282: #endif
2283:       /* C quad */
2284:       coneNew[0] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2285:       orntNew[0] = ornt[1];
2286:       coneNew[1] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2287:       orntNew[1] = ornt[2];
2288:       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
2289:       orntNew[2] = 0;
2290:       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
2291:       orntNew[3] = -2;
2292:       DMPlexSetCone(rdm, newp+2, coneNew);
2293:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2294: #if defined(PETSC_USE_DEBUG)
2295:       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
2296:       for (p = 0; p < 4; ++p) {
2297:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2298:       }
2299: #endif
2300:     }
2301:     /*
2302:      2---------1---------3
2303:      |         |         |
2304:      |    D    1    C    |
2305:      |         |         |
2306:      2----2----0----3----3
2307:      |         |         |
2308:      |    A    0    B    |
2309:      |         |         |
2310:      0---------0---------1
2311:      */
2312:     /* Parent cells are input as prisms but children are quads, since the mesh is no longer hybrid */
2313:     for (c = cMax; c < cEnd; ++c) {
2314:       const PetscInt  newp  = cStartNew + (cMax - cStart)*3 + (c - cMax)*4;
2315:       const PetscInt  newpt = (cMax - cStart)*3 + (c - cMax)*4;
2316:       const PetscInt *cone, *ornt;
2317:       PetscInt        coneNew[4], orntNew[4];

2319:       DMPlexGetCone(dm, c, &cone);
2320:       DMPlexGetConeOrientation(dm, c, &ornt);
2321:       /* A quad */
2322:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2323:       orntNew[0] = ornt[0];
2324:       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + newpt + 0;
2325:       orntNew[1] = 0;
2326:       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + newpt + 2;
2327:       orntNew[2] = -2;
2328:       coneNew[3] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2329:       orntNew[3] = ornt[2] < 0 ? 0 : -2;
2330:       DMPlexSetCone(rdm, newp+0, coneNew);
2331:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2332: #if defined(PETSC_USE_DEBUG)
2333:       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
2334:       for (p = 0; p < 4; ++p) {
2335:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2336:       }
2337: #endif
2338:       /* B quad */
2339:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2340:       orntNew[0] = ornt[0];
2341:       coneNew[1] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
2342:       orntNew[1] = ornt[3];
2343:       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + newpt + 3;
2344:       orntNew[2] = 0;
2345:       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + newpt + 0;
2346:       orntNew[3] = -2;
2347:       DMPlexSetCone(rdm, newp+1, coneNew);
2348:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2349: #if defined(PETSC_USE_DEBUG)
2350:       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
2351:       for (p = 0; p < 4; ++p) {
2352:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2353:       }
2354: #endif
2355:       /* C quad */
2356:       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + newpt + 3;
2357:       orntNew[0] = -2;
2358:       coneNew[1] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
2359:       orntNew[1] = ornt[3];
2360:       coneNew[2] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2361:       orntNew[2] = ornt[1] < 0 ? 0 : -2;
2362:       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + newpt + 1;
2363:       orntNew[3] = 0;
2364:       DMPlexSetCone(rdm, newp+2, coneNew);
2365:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2366: #if defined(PETSC_USE_DEBUG)
2367:       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
2368:       for (p = 0; p < 4; ++p) {
2369:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2370:       }
2371: #endif
2372:       /* D quad */
2373:       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + newpt + 2;
2374:       orntNew[0] = 0;
2375:       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + newpt + 1;
2376:       orntNew[1] = -2;
2377:       coneNew[2] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2378:       orntNew[2] = ornt[1] < 0 ? 0 : -2;
2379:       coneNew[3] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2380:       orntNew[3] = ornt[2] < 0 ? 0 : -2;
2381:       DMPlexSetCone(rdm, newp+3, coneNew);
2382:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2383: #if defined(PETSC_USE_DEBUG)
2384:       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
2385:       for (p = 0; p < 4; ++p) {
2386:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2387:       }
2388: #endif
2389:     }
2390:     /* Split faces have 2 vertices and the same cells as the parent */
2391:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
2392:     PetscMalloc1(2 + maxSupportSize*2, &supportRef);
2393:     for (f = fStart; f < fEnd; ++f) {
2394:       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);

2396:       for (r = 0; r < 2; ++r) {
2397:         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
2398:         const PetscInt *cone, *ornt, *support;
2399:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

2401:         DMPlexGetCone(dm, f, &cone);
2402:         coneNew[0]       = vStartNew + (cone[0] - vStart);
2403:         coneNew[1]       = vStartNew + (cone[1] - vStart);
2404:         coneNew[(r+1)%2] = newv;
2405:         DMPlexSetCone(rdm, newp, coneNew);
2406: #if defined(PETSC_USE_DEBUG)
2407:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2408:         for (p = 0; p < 2; ++p) {
2409:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2410:         }
2411: #endif
2412:         DMPlexGetSupportSize(dm, f, &supportSize);
2413:         DMPlexGetSupport(dm, f, &support);
2414:         for (s = 0; s < supportSize; ++s) {
2415:           const PetscInt p2q[4][2] = { {0, 1},
2416:                                        {3, 2},
2417:                                        {0, 3},
2418:                                        {1, 2} };

2420:           DMPlexGetConeSize(dm, support[s], &coneSize);
2421:           DMPlexGetCone(dm, support[s], &cone);
2422:           DMPlexGetConeOrientation(dm, support[s], &ornt);
2423:           for (c = 0; c < coneSize; ++c) {
2424:             if (cone[c] == f) break;
2425:           }
2426:           if (coneSize == 3)      supportRef[s] = cStartNew + (support[s] - cStart)*3 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
2427:           else if (coneSize == 4) supportRef[s] = cStartNew + (cMax - cStart)*3 + (support[s] - cMax)*4 + (ornt[c] < 0 ? p2q[c][(r+1)%2] : p2q[c][r]);
2428:           else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected cone size %D", coneSize);
2429:         }
2430:         DMPlexSetSupport(rdm, newp, supportRef);
2431: #if defined(PETSC_USE_DEBUG)
2432:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2433:         for (p = 0; p < supportSize; ++p) {
2434:           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
2435:         }
2436: #endif
2437:       }
2438:     }
2439:     /* Interior faces have 2 vertices and 2 cells */
2440:     for (c = cStart; c < cMax; ++c) {
2441:       const PetscInt *cone;

2443:       DMPlexGetCone(dm, c, &cone);
2444:       for (r = 0; r < 3; ++r) {
2445:         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
2446:         PetscInt       coneNew[2];
2447:         PetscInt       supportNew[2];

2449:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2450:         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
2451:         DMPlexSetCone(rdm, newp, coneNew);
2452: #if defined(PETSC_USE_DEBUG)
2453:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2454:         for (p = 0; p < 2; ++p) {
2455:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2456:         }
2457: #endif
2458:         supportNew[0] = (c - cStart)*3 + r%3;
2459:         supportNew[1] = (c - cStart)*3 + (r+1)%3;
2460:         DMPlexSetSupport(rdm, newp, supportNew);
2461: #if defined(PETSC_USE_DEBUG)
2462:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2463:         for (p = 0; p < 2; ++p) {
2464:           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
2465:         }
2466: #endif
2467:       }
2468:     }
2469:     /* Hybrid interior faces have 2 vertices and 2 cells */
2470:     for (c = cMax; c < cEnd; ++c) {
2471:       const PetscInt *cone;
2472:       PetscInt        coneNew[2], supportNew[2];

2474:       DMPlexGetCone(dm, c, &cone);
2475:       for (r = 0; r < 4; ++r) {
2476:         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (c - cMax)*4 + r;

2478:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2479:         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (cMax - cStart) + (c - cMax);
2480:         DMPlexSetCone(rdm, newp, coneNew);
2481: #if defined(PETSC_USE_DEBUG)
2482:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2483:         for (p = 0; p < 2; ++p) {
2484:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2485:         }
2486: #endif
2487:         if (r==0) {
2488:           supportNew[0] = (cMax - cStart)*3 + (c - cMax)*4 + 0;
2489:           supportNew[1] = (cMax - cStart)*3 + (c - cMax)*4 + 1;
2490:         } else if (r==1) {
2491:           supportNew[0] = (cMax - cStart)*3 + (c - cMax)*4 + 2;
2492:           supportNew[1] = (cMax - cStart)*3 + (c - cMax)*4 + 3;
2493:         } else if (r==2) {
2494:           supportNew[0] = (cMax - cStart)*3 + (c - cMax)*4 + 0;
2495:           supportNew[1] = (cMax - cStart)*3 + (c - cMax)*4 + 3;
2496:         } else {
2497:           supportNew[0] = (cMax - cStart)*3 + (c - cMax)*4 + 1;
2498:           supportNew[1] = (cMax - cStart)*3 + (c - cMax)*4 + 2;
2499:         }
2500:         DMPlexSetSupport(rdm, newp, supportNew);
2501: #if defined(PETSC_USE_DEBUG)
2502:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2503:         for (p = 0; p < 2; ++p) {
2504:           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
2505:         }
2506: #endif
2507:       }
2508:     }
2509:     /* Old vertices have identical supports */
2510:     for (v = vStart; v < vEnd; ++v) {
2511:       const PetscInt  newp = vStartNew + (v - vStart);
2512:       const PetscInt *support, *cone;
2513:       PetscInt        size, s;

2515:       DMPlexGetSupportSize(dm, v, &size);
2516:       DMPlexGetSupport(dm, v, &support);
2517:       for (s = 0; s < size; ++s) {
2518:         PetscInt r = 0;

2520:         DMPlexGetCone(dm, support[s], &cone);
2521:         if (cone[1] == v) r = 1;
2522:         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
2523:       }
2524:       DMPlexSetSupport(rdm, newp, supportRef);
2525: #if defined(PETSC_USE_DEBUG)
2526:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2527:       for (p = 0; p < size; ++p) {
2528:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2529:       }
2530: #endif
2531:     }
2532:     /* Split-face vertices have cells + 2 supports */
2533:     for (f = fStart; f < fEnd; ++f) {
2534:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
2535:       const PetscInt *cone, *support;
2536:       PetscInt        size, s;

2538:       DMPlexGetSupportSize(dm, f, &size);
2539:       DMPlexGetSupport(dm, f, &support);
2540:       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2541:       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2542:       for (s = 0; s < size; ++s) {
2543:         PetscInt r = 0, coneSize;

2545:         DMPlexGetCone(dm, support[s], &cone);
2546:         DMPlexGetConeSize(dm, support[s], &coneSize);
2547:         if (coneSize == 3) {
2548:           if      (cone[1] == f) r = 1;
2549:           else if (cone[2] == f) r = 2;
2550:           supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
2551:         } else if (coneSize == 4) {
2552:           if      (cone[1] == f) r = 1;
2553:           else if (cone[2] == f) r = 2;
2554:           else if (cone[3] == f) r = 3;
2555:           supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (support[s] - cMax)*4 + r;
2556:         } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected cone size %D", coneSize);
2557:       }
2558:       DMPlexSetSupport(rdm, newp, supportRef);
2559: #if defined(PETSC_USE_DEBUG)
2560:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2561:       for (p = 0; p < 2+size; ++p) {
2562:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2563:       }
2564: #endif
2565:     }
2566:     /* Interior vertices have 3 supports */
2567:     for (c = cStart; c < cMax; ++c) {
2568:       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;

2570:       supportRef[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
2571:       supportRef[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
2572:       supportRef[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
2573:       DMPlexSetSupport(rdm, newp, supportRef);
2574:     }
2575:     /* Hybrid interior vertices have 4 supports */
2576:     for (c = cMax; c < cEnd; ++c) {
2577:       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;

2579:       supportRef[0] = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (c - cMax)*4 + 0;
2580:       supportRef[1] = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (c - cMax)*4 + 1;
2581:       supportRef[2] = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (c - cMax)*4 + 2;
2582:       supportRef[3] = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (c - cMax)*4 + 3;
2583:       DMPlexSetSupport(rdm, newp, supportRef);
2584:     }
2585:     PetscFree(supportRef);
2586:     break;
2587:   case REFINER_HEX_2D:
2588:     /*
2589:      3---------2---------2
2590:      |         |         |
2591:      |    D    2    C    |
2592:      |         |         |
2593:      3----3----0----1----1
2594:      |         |         |
2595:      |    A    0    B    |
2596:      |         |         |
2597:      0---------0---------1
2598:      */
2599:     /* All cells have 4 faces */
2600:     for (c = cStart; c < cEnd; ++c) {
2601:       const PetscInt  newp = (c - cStart)*4;
2602:       const PetscInt *cone, *ornt;
2603:       PetscInt        coneNew[4], orntNew[4];

2605:       DMPlexGetCone(dm, c, &cone);
2606:       DMPlexGetConeOrientation(dm, c, &ornt);
2607:       /* A quad */
2608:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2609:       orntNew[0] = ornt[0];
2610:       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
2611:       orntNew[1] = 0;
2612:       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
2613:       orntNew[2] = -2;
2614:       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
2615:       orntNew[3] = ornt[3];
2616:       DMPlexSetCone(rdm, newp+0, coneNew);
2617:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2618: #if defined(PETSC_USE_DEBUG)
2619:       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
2620:       for (p = 0; p < 4; ++p) {
2621:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2622:       }
2623: #endif
2624:       /* B quad */
2625:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2626:       orntNew[0] = ornt[0];
2627:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2628:       orntNew[1] = ornt[1];
2629:       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
2630:       orntNew[2] = -2;
2631:       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
2632:       orntNew[3] = -2;
2633:       DMPlexSetCone(rdm, newp+1, coneNew);
2634:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2635: #if defined(PETSC_USE_DEBUG)
2636:       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
2637:       for (p = 0; p < 4; ++p) {
2638:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2639:       }
2640: #endif
2641:       /* C quad */
2642:       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
2643:       orntNew[0] = 0;
2644:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2645:       orntNew[1] = ornt[1];
2646:       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2647:       orntNew[2] = ornt[2];
2648:       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
2649:       orntNew[3] = -2;
2650:       DMPlexSetCone(rdm, newp+2, coneNew);
2651:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2652: #if defined(PETSC_USE_DEBUG)
2653:       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
2654:       for (p = 0; p < 4; ++p) {
2655:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2656:       }
2657: #endif
2658:       /* D quad */
2659:       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
2660:       orntNew[0] = 0;
2661:       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
2662:       orntNew[1] = 0;
2663:       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2664:       orntNew[2] = ornt[2];
2665:       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
2666:       orntNew[3] = ornt[3];
2667:       DMPlexSetCone(rdm, newp+3, coneNew);
2668:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2669: #if defined(PETSC_USE_DEBUG)
2670:       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
2671:       for (p = 0; p < 4; ++p) {
2672:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2673:       }
2674: #endif
2675:     }
2676:     /* Split faces have 2 vertices and the same cells as the parent */
2677:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
2678:     PetscMalloc1(2 + maxSupportSize*2, &supportRef);
2679:     for (f = fStart; f < fEnd; ++f) {
2680:       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);

2682:       for (r = 0; r < 2; ++r) {
2683:         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
2684:         const PetscInt *cone, *ornt, *support;
2685:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

2687:         DMPlexGetCone(dm, f, &cone);
2688:         coneNew[0]       = vStartNew + (cone[0] - vStart);
2689:         coneNew[1]       = vStartNew + (cone[1] - vStart);
2690:         coneNew[(r+1)%2] = newv;
2691:         DMPlexSetCone(rdm, newp, coneNew);
2692: #if defined(PETSC_USE_DEBUG)
2693:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2694:         for (p = 0; p < 2; ++p) {
2695:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2696:         }
2697: #endif
2698:         DMPlexGetSupportSize(dm, f, &supportSize);
2699:         DMPlexGetSupport(dm, f, &support);
2700:         for (s = 0; s < supportSize; ++s) {
2701:           DMPlexGetConeSize(dm, support[s], &coneSize);
2702:           DMPlexGetCone(dm, support[s], &cone);
2703:           DMPlexGetConeOrientation(dm, support[s], &ornt);
2704:           for (c = 0; c < coneSize; ++c) {
2705:             if (cone[c] == f) break;
2706:           }
2707:           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
2708:         }
2709:         DMPlexSetSupport(rdm, newp, supportRef);
2710: #if defined(PETSC_USE_DEBUG)
2711:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2712:         for (p = 0; p < supportSize; ++p) {
2713:           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
2714:         }
2715: #endif
2716:       }
2717:     }
2718:     /* Interior faces have 2 vertices and 2 cells */
2719:     for (c = cStart; c < cEnd; ++c) {
2720:       const PetscInt *cone;
2721:       PetscInt        coneNew[2], supportNew[2];

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

2727:         if (r==1 || r==2) {
2728:           coneNew[0] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
2729:           coneNew[1] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2730:         } else {
2731:           coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2732:           coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
2733:         }
2734:         DMPlexSetCone(rdm, newp, coneNew);
2735: #if defined(PETSC_USE_DEBUG)
2736:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2737:         for (p = 0; p < 2; ++p) {
2738:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2739:         }
2740: #endif
2741:         supportNew[0] = (c - cStart)*4 + r;
2742:         supportNew[1] = (c - cStart)*4 + (r+1)%4;
2743:         DMPlexSetSupport(rdm, newp, supportNew);
2744: #if defined(PETSC_USE_DEBUG)
2745:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2746:         for (p = 0; p < 2; ++p) {
2747:           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
2748:         }
2749: #endif
2750:       }
2751:     }
2752:     /* Old vertices have identical supports */
2753:     for (v = vStart; v < vEnd; ++v) {
2754:       const PetscInt  newp = vStartNew + (v - vStart);
2755:       const PetscInt *support, *cone;
2756:       PetscInt        size, s;

2758:       DMPlexGetSupportSize(dm, v, &size);
2759:       DMPlexGetSupport(dm, v, &support);
2760:       for (s = 0; s < size; ++s) {
2761:         PetscInt r = 0;

2763:         DMPlexGetCone(dm, support[s], &cone);
2764:         if (cone[1] == v) r = 1;
2765:         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
2766:       }
2767:       DMPlexSetSupport(rdm, newp, supportRef);
2768: #if defined(PETSC_USE_DEBUG)
2769:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2770:       for (p = 0; p < size; ++p) {
2771:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2772:       }
2773: #endif
2774:     }
2775:     /* Face vertices have 2 + cells supports */
2776:     for (f = fStart; f < fEnd; ++f) {
2777:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
2778:       const PetscInt *cone, *support;
2779:       PetscInt        size, s;

2781:       DMPlexGetSupportSize(dm, f, &size);
2782:       DMPlexGetSupport(dm, f, &support);
2783:       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2784:       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2785:       for (s = 0; s < size; ++s) {
2786:         PetscInt r = 0;

2788:         DMPlexGetCone(dm, support[s], &cone);
2789:         if      (cone[1] == f) r = 1;
2790:         else if (cone[2] == f) r = 2;
2791:         else if (cone[3] == f) r = 3;
2792:         supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r;
2793:       }
2794:       DMPlexSetSupport(rdm, newp, supportRef);
2795: #if defined(PETSC_USE_DEBUG)
2796:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
2797:       for (p = 0; p < 2+size; ++p) {
2798:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
2799:       }
2800: #endif
2801:     }
2802:     /* Cell vertices have 4 supports */
2803:     for (c = cStart; c < cEnd; ++c) {
2804:       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
2805:       PetscInt       supportNew[4];

2807:       for (r = 0; r < 4; ++r) {
2808:         supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
2809:       }
2810:       DMPlexSetSupport(rdm, newp, supportNew);
2811:     }
2812:     PetscFree(supportRef);
2813:     break;
2814:   case REFINER_HYBRID_SIMPLEX_2D:
2815:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
2816:     cMax = PetscMin(cEnd, cMax);
2817:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
2818:     fMax = PetscMin(fEnd, fMax);
2819:     DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, NULL, NULL);
2820:     /* Interior cells have 3 faces */
2821:     for (c = cStart; c < cMax; ++c) {
2822:       const PetscInt  newp = cStartNew + (c - cStart)*4;
2823:       const PetscInt *cone, *ornt;
2824:       PetscInt        coneNew[3], orntNew[3];

2826:       DMPlexGetCone(dm, c, &cone);
2827:       DMPlexGetConeOrientation(dm, c, &ornt);
2828:       /* A triangle */
2829:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2830:       orntNew[0] = ornt[0];
2831:       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
2832:       orntNew[1] = -2;
2833:       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2834:       orntNew[2] = ornt[2];
2835:       DMPlexSetCone(rdm, newp+0, coneNew);
2836:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2837: #if defined(PETSC_USE_DEBUG)
2838:       if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+0, cStartNew, cMaxNew);
2839:       for (p = 0; p < 3; ++p) {
2840:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
2841:       }
2842: #endif
2843:       /* B triangle */
2844:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2845:       orntNew[0] = ornt[0];
2846:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2847:       orntNew[1] = ornt[1];
2848:       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
2849:       orntNew[2] = -2;
2850:       DMPlexSetCone(rdm, newp+1, coneNew);
2851:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2852: #if defined(PETSC_USE_DEBUG)
2853:       if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+1, cStartNew, cMaxNew);
2854:       for (p = 0; p < 3; ++p) {
2855:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
2856:       }
2857: #endif
2858:       /* C triangle */
2859:       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
2860:       orntNew[0] = -2;
2861:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2862:       orntNew[1] = ornt[1];
2863:       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2864:       orntNew[2] = ornt[2];
2865:       DMPlexSetCone(rdm, newp+2, coneNew);
2866:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2867: #if defined(PETSC_USE_DEBUG)
2868:       if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+2, cStartNew, cMaxNew);
2869:       for (p = 0; p < 3; ++p) {
2870:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
2871:       }
2872: #endif
2873:       /* D triangle */
2874:       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
2875:       orntNew[0] = 0;
2876:       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
2877:       orntNew[1] = 0;
2878:       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
2879:       orntNew[2] = 0;
2880:       DMPlexSetCone(rdm, newp+3, coneNew);
2881:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2882: #if defined(PETSC_USE_DEBUG)
2883:       if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+3, cStartNew, cMaxNew);
2884:       for (p = 0; p < 3; ++p) {
2885:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
2886:       }
2887: #endif
2888:     }
2889:     /*
2890:      2----3----3
2891:      |         |
2892:      |    B    |
2893:      |         |
2894:      0----4--- 1
2895:      |         |
2896:      |    A    |
2897:      |         |
2898:      0----2----1
2899:      */
2900:     /* Hybrid cells have 4 faces */
2901:     for (c = cMax; c < cEnd; ++c) {
2902:       const PetscInt  newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
2903:       const PetscInt *cone, *ornt;
2904:       PetscInt        coneNew[4], orntNew[4], r;

2906:       DMPlexGetCone(dm, c, &cone);
2907:       DMPlexGetConeOrientation(dm, c, &ornt);
2908:       r    = (ornt[0] < 0 ? 1 : 0);
2909:       /* A quad */
2910:       coneNew[0]   = fStartNew + (cone[0] - fStart)*2 + r;
2911:       orntNew[0]   = ornt[0];
2912:       coneNew[1]   = fStartNew + (cone[1] - fStart)*2 + r;
2913:       orntNew[1]   = ornt[1];
2914:       coneNew[2+r] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[2+r] - fMax);
2915:       orntNew[2+r] = 0;
2916:       coneNew[3-r] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
2917:       orntNew[3-r] = 0;
2918:       DMPlexSetCone(rdm, newp+0, coneNew);
2919:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2920: #if defined(PETSC_USE_DEBUG)
2921:       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
2922:       for (p = 0; p < 4; ++p) {
2923:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2924:       }
2925: #endif
2926:       /* B quad */
2927:       coneNew[0]   = fStartNew + (cone[0] - fStart)*2 + 1-r;
2928:       orntNew[0]   = ornt[0];
2929:       coneNew[1]   = fStartNew + (cone[1] - fStart)*2 + 1-r;
2930:       orntNew[1]   = ornt[1];
2931:       coneNew[2+r] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
2932:       orntNew[2+r] = 0;
2933:       coneNew[3-r] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[3-r] - fMax);
2934:       orntNew[3-r] = 0;
2935:       DMPlexSetCone(rdm, newp+1, coneNew);
2936:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2937: #if defined(PETSC_USE_DEBUG)
2938:       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
2939:       for (p = 0; p < 4; ++p) {
2940:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
2941:       }
2942: #endif
2943:     }
2944:     /* Interior split faces have 2 vertices and the same cells as the parent */
2945:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
2946:     PetscMalloc1(2 + maxSupportSize*2, &supportRef);
2947:     for (f = fStart; f < fMax; ++f) {
2948:       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);

2950:       for (r = 0; r < 2; ++r) {
2951:         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
2952:         const PetscInt *cone, *ornt, *support;
2953:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

2955:         DMPlexGetCone(dm, f, &cone);
2956:         coneNew[0]       = vStartNew + (cone[0] - vStart);
2957:         coneNew[1]       = vStartNew + (cone[1] - vStart);
2958:         coneNew[(r+1)%2] = newv;
2959:         DMPlexSetCone(rdm, newp, coneNew);
2960: #if defined(PETSC_USE_DEBUG)
2961:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2962:         for (p = 0; p < 2; ++p) {
2963:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
2964:         }
2965: #endif
2966:         DMPlexGetSupportSize(dm, f, &supportSize);
2967:         DMPlexGetSupport(dm, f, &support);
2968:         for (s = 0; s < supportSize; ++s) {
2969:           DMPlexGetConeSize(dm, support[s], &coneSize);
2970:           DMPlexGetCone(dm, support[s], &cone);
2971:           DMPlexGetConeOrientation(dm, support[s], &ornt);
2972:           for (c = 0; c < coneSize; ++c) if (cone[c] == f) break;
2973:           if (support[s] >= cMax) {
2974:             supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + (ornt[c] < 0 ? 1-r : r);
2975:           } else {
2976:             supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
2977:           }
2978:         }
2979:         DMPlexSetSupport(rdm, newp, supportRef);
2980: #if defined(PETSC_USE_DEBUG)
2981:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
2982:         for (p = 0; p < supportSize; ++p) {
2983:           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
2984:         }
2985: #endif
2986:       }
2987:     }
2988:     /* Interior cell faces have 2 vertices and 2 cells */
2989:     for (c = cStart; c < cMax; ++c) {
2990:       const PetscInt *cone;

2992:       DMPlexGetCone(dm, c, &cone);
2993:       for (r = 0; r < 3; ++r) {
2994:         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
2995:         PetscInt       coneNew[2];
2996:         PetscInt       supportNew[2];

2998:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
2999:         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
3000:         DMPlexSetCone(rdm, newp, coneNew);
3001: #if defined(PETSC_USE_DEBUG)
3002:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3003:         for (p = 0; p < 2; ++p) {
3004:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3005:         }
3006: #endif
3007:         supportNew[0] = (c - cStart)*4 + (r+1)%3;
3008:         supportNew[1] = (c - cStart)*4 + 3;
3009:         DMPlexSetSupport(rdm, newp, supportNew);
3010: #if defined(PETSC_USE_DEBUG)
3011:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3012:         for (p = 0; p < 2; ++p) {
3013:           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3014:         }
3015: #endif
3016:       }
3017:     }
3018:     /* Interior hybrid faces have 2 vertices and the same cells */
3019:     for (f = fMax; f < fEnd; ++f) {
3020:       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
3021:       const PetscInt *cone, *ornt;
3022:       const PetscInt *support;
3023:       PetscInt        coneNew[2];
3024:       PetscInt        supportNew[2];
3025:       PetscInt        size, s, r;

3027:       DMPlexGetCone(dm, f, &cone);
3028:       coneNew[0] = vStartNew + (cone[0] - vStart);
3029:       coneNew[1] = vStartNew + (cone[1] - vStart);
3030:       DMPlexSetCone(rdm, newp, coneNew);
3031: #if defined(PETSC_USE_DEBUG)
3032:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3033:       for (p = 0; p < 2; ++p) {
3034:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3035:       }
3036: #endif
3037:       DMPlexGetSupportSize(dm, f, &size);
3038:       DMPlexGetSupport(dm, f, &support);
3039:       for (s = 0; s < size; ++s) {
3040:         DMPlexGetCone(dm, support[s], &cone);
3041:         DMPlexGetConeOrientation(dm, support[s], &ornt);
3042:         for (r = 0; r < 2; ++r) {
3043:           if (cone[r+2] == f) break;
3044:         }
3045:         supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + (ornt[0] < 0 ? 1-r : r);
3046:       }
3047:       DMPlexSetSupport(rdm, newp, supportNew);
3048: #if defined(PETSC_USE_DEBUG)
3049:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3050:       for (p = 0; p < size; ++p) {
3051:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3052:       }
3053: #endif
3054:     }
3055:     /* Cell hybrid faces have 2 vertices and 2 cells */
3056:     for (c = cMax; c < cEnd; ++c) {
3057:       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
3058:       const PetscInt *cone;
3059:       PetscInt        coneNew[2];
3060:       PetscInt        supportNew[2];

3062:       DMPlexGetCone(dm, c, &cone);
3063:       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
3064:       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
3065:       DMPlexSetCone(rdm, newp, coneNew);
3066: #if defined(PETSC_USE_DEBUG)
3067:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3068:       for (p = 0; p < 2; ++p) {
3069:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3070:       }
3071: #endif
3072:       supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
3073:       supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
3074:       DMPlexSetSupport(rdm, newp, supportNew);
3075: #if defined(PETSC_USE_DEBUG)
3076:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3077:       for (p = 0; p < 2; ++p) {
3078:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3079:       }
3080: #endif
3081:     }
3082:     /* Old vertices have identical supports */
3083:     for (v = vStart; v < vEnd; ++v) {
3084:       const PetscInt  newp = vStartNew + (v - vStart);
3085:       const PetscInt *support, *cone;
3086:       PetscInt        size, s;

3088:       DMPlexGetSupportSize(dm, v, &size);
3089:       DMPlexGetSupport(dm, v, &support);
3090:       for (s = 0; s < size; ++s) {
3091:         if (support[s] >= fMax) {
3092:           supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax);
3093:         } else {
3094:           PetscInt r = 0;

3096:           DMPlexGetCone(dm, support[s], &cone);
3097:           if (cone[1] == v) r = 1;
3098:           supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
3099:         }
3100:       }
3101:       DMPlexSetSupport(rdm, newp, supportRef);
3102: #if defined(PETSC_USE_DEBUG)
3103:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
3104:       for (p = 0; p < size; ++p) {
3105:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
3106:       }
3107: #endif
3108:     }
3109:     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
3110:     for (f = fStart; f < fMax; ++f) {
3111:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
3112:       const PetscInt *cone, *support;
3113:       PetscInt        size, newSize = 2, s;

3115:       DMPlexGetSupportSize(dm, f, &size);
3116:       DMPlexGetSupport(dm, f, &support);
3117:       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
3118:       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
3119:       for (s = 0; s < size; ++s) {
3120:         PetscInt r = 0;

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

3126:           newSize += 1;
3127:         } else {
3128:           if      (cone[1] == f) r = 1;
3129:           else if (cone[2] == f) r = 2;
3130:           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
3131:           supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r;

3133:           newSize += 2;
3134:         }
3135:       }
3136:       DMPlexSetSupport(rdm, newp, supportRef);
3137: #if defined(PETSC_USE_DEBUG)
3138:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
3139:       for (p = 0; p < newSize; ++p) {
3140:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
3141:       }
3142: #endif
3143:     }
3144:     PetscFree(supportRef);
3145:     break;
3146:   case REFINER_HYBRID_HEX_2D:
3147:     /* Hybrid Hex 2D */
3148:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
3149:     cMax = PetscMin(cEnd, cMax);
3150:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
3151:     fMax = PetscMin(fEnd, fMax);
3152:     DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, NULL, NULL);
3153:     /* Interior cells have 4 faces */
3154:     for (c = cStart; c < cMax; ++c) {
3155:       const PetscInt  newp = cStartNew + (c - cStart)*4;
3156:       const PetscInt *cone, *ornt;
3157:       PetscInt        coneNew[4], orntNew[4];

3159:       DMPlexGetCone(dm, c, &cone);
3160:       DMPlexGetConeOrientation(dm, c, &ornt);
3161:       /* A quad */
3162:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
3163:       orntNew[0] = ornt[0];
3164:       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 0;
3165:       orntNew[1] = 0;
3166:       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 3;
3167:       orntNew[2] = -2;
3168:       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
3169:       orntNew[3] = ornt[3];
3170:       DMPlexSetCone(rdm, newp+0, coneNew);
3171:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
3172: #if defined(PETSC_USE_DEBUG)
3173:       if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+0, cStartNew, cMaxNew);
3174:       for (p = 0; p < 4; ++p) {
3175:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
3176:       }
3177: #endif
3178:       /* B quad */
3179:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
3180:       orntNew[0] = ornt[0];
3181:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
3182:       orntNew[1] = ornt[1];
3183:       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 1;
3184:       orntNew[2] = 0;
3185:       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 0;
3186:       orntNew[3] = -2;
3187:       DMPlexSetCone(rdm, newp+1, coneNew);
3188:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
3189: #if defined(PETSC_USE_DEBUG)
3190:       if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+1, cStartNew, cMaxNew);
3191:       for (p = 0; p < 4; ++p) {
3192:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
3193:       }
3194: #endif
3195:       /* C quad */
3196:       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 1;
3197:       orntNew[0] = -2;
3198:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
3199:       orntNew[1] = ornt[1];
3200:       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
3201:       orntNew[2] = ornt[2];
3202:       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 2;
3203:       orntNew[3] = 0;
3204:       DMPlexSetCone(rdm, newp+2, coneNew);
3205:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
3206: #if defined(PETSC_USE_DEBUG)
3207:       if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+2, cStartNew, cMaxNew);
3208:       for (p = 0; p < 4; ++p) {
3209:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
3210:       }
3211: #endif
3212:       /* D quad */
3213:       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 3;
3214:       orntNew[0] = 0;
3215:       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*4 + 2;
3216:       orntNew[1] = -2;
3217:       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
3218:       orntNew[2] = ornt[2];
3219:       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
3220:       orntNew[3] = ornt[3];
3221:       DMPlexSetCone(rdm, newp+3, coneNew);
3222:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3223: #if defined(PETSC_USE_DEBUG)
3224:       if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior cell [%D, %D)", newp+3, cStartNew, cMaxNew);
3225:       for (p = 0; p < 4; ++p) {
3226:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
3227:       }
3228: #endif
3229:     }
3230:     /*
3231:      2----3----3
3232:      |         |
3233:      |    B    |
3234:      |         |
3235:      0----4--- 1
3236:      |         |
3237:      |    A    |
3238:      |         |
3239:      0----2----1
3240:      */
3241:     /* Hybrid cells have 4 faces */
3242:     for (c = cMax; c < cEnd; ++c) {
3243:       const PetscInt  newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
3244:       const PetscInt *cone, *ornt;
3245:       PetscInt        coneNew[4], orntNew[4];

3247:       DMPlexGetCone(dm, c, &cone);
3248:       DMPlexGetConeOrientation(dm, c, &ornt);
3249:       /* A quad */
3250:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
3251:       orntNew[0] = ornt[0];
3252:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
3253:       orntNew[1] = ornt[1];
3254:       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*4 + (cone[2] - fMax);
3255:       orntNew[2] = 0;
3256:       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*4 + (fEnd    - fMax) + (c - cMax);
3257:       orntNew[3] = 0;
3258:       DMPlexSetCone(rdm, newp+0, coneNew);
3259:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
3260: #if defined(PETSC_USE_DEBUG)
3261:       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
3262:       for (p = 0; p < 4; ++p) {
3263:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3264:       }
3265: #endif
3266:       /* B quad */
3267:       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
3268:       orntNew[0] = ornt[0];
3269:       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
3270:       orntNew[1] = ornt[1];
3271:       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*4 + (fEnd    - fMax) + (c - cMax);
3272:       orntNew[2] = 0;
3273:       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*4 + (cone[3] - fMax);
3274:       orntNew[3] = 0;
3275:       DMPlexSetCone(rdm, newp+1, coneNew);
3276:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
3277: #if defined(PETSC_USE_DEBUG)
3278:       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
3279:       for (p = 0; p < 4; ++p) {
3280:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3281:       }
3282: #endif
3283:     }
3284:     /* Interior split faces have 2 vertices and the same cells as the parent */
3285:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
3286:     PetscMalloc1(2 + maxSupportSize*2, &supportRef);
3287:     for (f = fStart; f < fMax; ++f) {
3288:       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);

3290:       for (r = 0; r < 2; ++r) {
3291:         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
3292:         const PetscInt *cone, *ornt, *support;
3293:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

3295:         DMPlexGetCone(dm, f, &cone);
3296:         coneNew[0]       = vStartNew + (cone[0] - vStart);
3297:         coneNew[1]       = vStartNew + (cone[1] - vStart);
3298:         coneNew[(r+1)%2] = newv;
3299:         DMPlexSetCone(rdm, newp, coneNew);
3300: #if defined(PETSC_USE_DEBUG)
3301:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3302:         for (p = 0; p < 2; ++p) {
3303:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3304:         }
3305: #endif
3306:         DMPlexGetSupportSize(dm, f, &supportSize);
3307:         DMPlexGetSupport(dm, f, &support);
3308:         for (s = 0; s < supportSize; ++s) {
3309:           if (support[s] >= cMax) {
3310:             supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
3311:           } else {
3312:             DMPlexGetConeSize(dm, support[s], &coneSize);
3313:             DMPlexGetCone(dm, support[s], &cone);
3314:             DMPlexGetConeOrientation(dm, support[s], &ornt);
3315:             for (c = 0; c < coneSize; ++c) {
3316:               if (cone[c] == f) break;
3317:             }
3318:             supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
3319:           }
3320:         }
3321:         DMPlexSetSupport(rdm, newp, supportRef);
3322: #if defined(PETSC_USE_DEBUG)
3323:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3324:         for (p = 0; p < supportSize; ++p) {
3325:           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
3326:         }
3327: #endif
3328:       }
3329:     }
3330:     /* Interior cell faces have 2 vertices and 2 cells */
3331:     for (c = cStart; c < cMax; ++c) {
3332:       const PetscInt *cone;

3334:       DMPlexGetCone(dm, c, &cone);
3335:       for (r = 0; r < 4; ++r) {
3336:         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
3337:         PetscInt       coneNew[2], supportNew[2];

3339:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
3340:         coneNew[1] = vStartNew + (vEnd - vStart) + (fMax    - fStart) + (c - cStart);
3341:         DMPlexSetCone(rdm, newp, coneNew);
3342: #if defined(PETSC_USE_DEBUG)
3343:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3344:         for (p = 0; p < 2; ++p) {
3345:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3346:         }
3347: #endif
3348:         supportNew[0] = (c - cStart)*4 + r;
3349:         supportNew[1] = (c - cStart)*4 + (r+1)%4;
3350:         DMPlexSetSupport(rdm, newp, supportNew);
3351: #if defined(PETSC_USE_DEBUG)
3352:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3353:         for (p = 0; p < 2; ++p) {
3354:           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3355:         }
3356: #endif
3357:       }
3358:     }
3359:     /* Hybrid faces have 2 vertices and the same cells */
3360:     for (f = fMax; f < fEnd; ++f) {
3361:       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (f - fMax);
3362:       const PetscInt *cone, *support;
3363:       PetscInt        coneNew[2], supportNew[2];
3364:       PetscInt        size, s, r;

3366:       DMPlexGetCone(dm, f, &cone);
3367:       coneNew[0] = vStartNew + (cone[0] - vStart);
3368:       coneNew[1] = vStartNew + (cone[1] - vStart);
3369:       DMPlexSetCone(rdm, newp, coneNew);
3370: #if defined(PETSC_USE_DEBUG)
3371:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3372:       for (p = 0; p < 2; ++p) {
3373:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3374:       }
3375: #endif
3376:       DMPlexGetSupportSize(dm, f, &size);
3377:       DMPlexGetSupport(dm, f, &support);
3378:       for (s = 0; s < size; ++s) {
3379:         DMPlexGetCone(dm, support[s], &cone);
3380:         for (r = 0; r < 2; ++r) {
3381:           if (cone[r+2] == f) break;
3382:         }
3383:         supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
3384:       }
3385:       DMPlexSetSupport(rdm, newp, supportNew);
3386: #if defined(PETSC_USE_DEBUG)
3387:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3388:       for (p = 0; p < size; ++p) {
3389:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3390:       }
3391: #endif
3392:     }
3393:     /* Cell hybrid faces have 2 vertices and 2 cells */
3394:     for (c = cMax; c < cEnd; ++c) {
3395:       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
3396:       const PetscInt *cone;
3397:       PetscInt        coneNew[2], supportNew[2];

3399:       DMPlexGetCone(dm, c, &cone);
3400:       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
3401:       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
3402:       DMPlexSetCone(rdm, newp, coneNew);
3403: #if defined(PETSC_USE_DEBUG)
3404:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3405:       for (p = 0; p < 2; ++p) {
3406:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3407:       }
3408: #endif
3409:       supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
3410:       supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
3411:       DMPlexSetSupport(rdm, newp, supportNew);
3412: #if defined(PETSC_USE_DEBUG)
3413:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3414:       for (p = 0; p < 2; ++p) {
3415:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3416:       }
3417: #endif
3418:     }
3419:     /* Old vertices have identical supports */
3420:     for (v = vStart; v < vEnd; ++v) {
3421:       const PetscInt  newp = vStartNew + (v - vStart);
3422:       const PetscInt *support, *cone;
3423:       PetscInt        size, s;

3425:       DMPlexGetSupportSize(dm, v, &size);
3426:       DMPlexGetSupport(dm, v, &support);
3427:       for (s = 0; s < size; ++s) {
3428:         if (support[s] >= fMax) {
3429:           supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (support[s] - fMax);
3430:         } else {
3431:           PetscInt r = 0;

3433:           DMPlexGetCone(dm, support[s], &cone);
3434:           if (cone[1] == v) r = 1;
3435:           supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
3436:         }
3437:       }
3438:       DMPlexSetSupport(rdm, newp, supportRef);
3439: #if defined(PETSC_USE_DEBUG)
3440:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
3441:       for (p = 0; p < size; ++p) {
3442:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
3443:       }
3444: #endif
3445:     }
3446:     /* Face vertices have 2 + cells supports */
3447:     for (f = fStart; f < fMax; ++f) {
3448:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
3449:       const PetscInt *cone, *support;
3450:       PetscInt        size, s;

3452:       DMPlexGetSupportSize(dm, f, &size);
3453:       DMPlexGetSupport(dm, f, &support);
3454:       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
3455:       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
3456:       for (s = 0; s < size; ++s) {
3457:         PetscInt r = 0;

3459:         DMPlexGetCone(dm, support[s], &cone);
3460:         if (support[s] >= cMax) {
3461:           supportRef[2+s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (support[s] - cMax);
3462:         } else {
3463:           if      (cone[1] == f) r = 1;
3464:           else if (cone[2] == f) r = 2;
3465:           else if (cone[3] == f) r = 3;
3466:           supportRef[2+s] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*4 + r;
3467:         }
3468:       }
3469:       DMPlexSetSupport(rdm, newp, supportRef);
3470: #if defined(PETSC_USE_DEBUG)
3471:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
3472:       for (p = 0; p < 2+size; ++p) {
3473:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
3474:       }
3475: #endif
3476:     }
3477:     /* Cell vertices have 4 supports */
3478:     for (c = cStart; c < cMax; ++c) {
3479:       const PetscInt newp = vStartNew + (vEnd - vStart) + (fMax - fStart) + (c - cStart);
3480:       PetscInt       supportNew[4];

3482:       for (r = 0; r < 4; ++r) {
3483:         supportNew[r] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
3484:       }
3485:       DMPlexSetSupport(rdm, newp, supportNew);
3486:     }
3487:     PetscFree(supportRef);
3488:     break;
3489:   case REFINER_SIMPLEX_3D:
3490:     /* All cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
3491:     DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
3492:     for (c = cStart; c < cEnd; ++c) {
3493:       const PetscInt  newp = cStartNew + (c - cStart)*8;
3494:       const PetscInt *cone, *ornt;
3495:       PetscInt        coneNew[4], orntNew[4];

3497:       DMPlexGetCone(dm, c, &cone);
3498:       DMPlexGetConeOrientation(dm, c, &ornt);
3499:       /* A tetrahedron: {0, a, c, d} */
3500:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
3501:       orntNew[0] = ornt[0];
3502:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
3503:       orntNew[1] = ornt[1];
3504:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
3505:       orntNew[2] = ornt[2];
3506:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
3507:       orntNew[3] = 0;
3508:       DMPlexSetCone(rdm, newp+0, coneNew);
3509:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
3510: #if defined(PETSC_USE_DEBUG)
3511:       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
3512:       for (p = 0; p < 4; ++p) {
3513:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3514:       }
3515: #endif
3516:       /* B tetrahedron: {a, 1, b, e} */
3517:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
3518:       orntNew[0] = ornt[0];
3519:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
3520:       orntNew[1] = ornt[1];
3521:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
3522:       orntNew[2] = 0;
3523:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
3524:       orntNew[3] = ornt[3];
3525:       DMPlexSetCone(rdm, newp+1, coneNew);
3526:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
3527: #if defined(PETSC_USE_DEBUG)
3528:       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
3529:       for (p = 0; p < 4; ++p) {
3530:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3531:       }
3532: #endif
3533:       /* C tetrahedron: {c, b, 2, f} */
3534:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
3535:       orntNew[0] = ornt[0];
3536:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
3537:       orntNew[1] = 0;
3538:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
3539:       orntNew[2] = ornt[2];
3540:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
3541:       orntNew[3] = ornt[3];
3542:       DMPlexSetCone(rdm, newp+2, coneNew);
3543:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
3544: #if defined(PETSC_USE_DEBUG)
3545:       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
3546:       for (p = 0; p < 4; ++p) {
3547:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3548:       }
3549: #endif
3550:       /* D tetrahedron: {d, e, f, 3} */
3551:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
3552:       orntNew[0] = 0;
3553:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
3554:       orntNew[1] = ornt[1];
3555:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
3556:       orntNew[2] = ornt[2];
3557:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
3558:       orntNew[3] = ornt[3];
3559:       DMPlexSetCone(rdm, newp+3, coneNew);
3560:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3561: #if defined(PETSC_USE_DEBUG)
3562:       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
3563:       for (p = 0; p < 4; ++p) {
3564:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3565:       }
3566: #endif
3567:       /* A' tetrahedron: {c, d, a, f} */
3568:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
3569:       orntNew[0] = -3;
3570:       coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
3571:       orntNew[1] = ornt[2] < 0 ? -(GetTriMidEdge_Static(ornt[2], 0)+1) : GetTriMidEdge_Static(ornt[2], 0);
3572:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
3573:       orntNew[2] = 0;
3574:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
3575:       orntNew[3] = 2;
3576:       DMPlexSetCone(rdm, newp+4, coneNew);
3577:       DMPlexSetConeOrientation(rdm, newp+4, orntNew);
3578: #if defined(PETSC_USE_DEBUG)
3579:       if ((newp+4 < cStartNew) || (newp+4 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+4, cStartNew, cEndNew);
3580:       for (p = 0; p < 4; ++p) {
3581:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3582:       }
3583: #endif
3584:       /* B' tetrahedron: {e, b, a, f} */
3585:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
3586:       orntNew[0] = -2;
3587:       coneNew[1] = fStartNew + (cone[3] - fStart)*4 + 3;
3588:       orntNew[1] = ornt[3] < 0 ? -(GetTriMidEdge_Static(ornt[3], 1)+1) : GetTriMidEdge_Static(ornt[3], 1);
3589:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
3590:       orntNew[2] = 0;
3591:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
3592:       orntNew[3] = 0;
3593:       DMPlexSetCone(rdm, newp+5, coneNew);
3594:       DMPlexSetConeOrientation(rdm, newp+5, orntNew);
3595: #if defined(PETSC_USE_DEBUG)
3596:       if ((newp+5 < cStartNew) || (newp+5 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+5, cStartNew, cEndNew);
3597:       for (p = 0; p < 4; ++p) {
3598:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3599:       }
3600: #endif
3601:       /* C' tetrahedron: {f, a, c, b} */
3602:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
3603:       orntNew[0] = -2;
3604:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
3605:       orntNew[1] = -2;
3606:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
3607:       orntNew[2] = -1;
3608:       coneNew[3] = fStartNew + (cone[0] - fStart)*4 + 3;
3609:       orntNew[3] = ornt[0] < 0 ? -(GetTriMidEdge_Static(ornt[0], 2)+1) : GetTriMidEdge_Static(ornt[0], 2);
3610:       DMPlexSetCone(rdm, newp+6, coneNew);
3611:       DMPlexSetConeOrientation(rdm, newp+6, orntNew);
3612: #if defined(PETSC_USE_DEBUG)
3613:       if ((newp+6 < cStartNew) || (newp+6 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+6, cStartNew, cEndNew);
3614:       for (p = 0; p < 4; ++p) {
3615:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3616:       }
3617: #endif
3618:       /* D' tetrahedron: {f, a, e, d} */
3619:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
3620:       orntNew[0] = -2;
3621:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
3622:       orntNew[1] = -1;
3623:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
3624:       orntNew[2] = -2;
3625:       coneNew[3] = fStartNew + (cone[1] - fStart)*4 + 3;
3626:       orntNew[3] = ornt[1] < 0 ? -(GetTriMidEdge_Static(ornt[1], 1)+1) : GetTriMidEdge_Static(ornt[1], 1);
3627:       DMPlexSetCone(rdm, newp+7, coneNew);
3628:       DMPlexSetConeOrientation(rdm, newp+7, orntNew);
3629: #if defined(PETSC_USE_DEBUG)
3630:       if ((newp+7 < cStartNew) || (newp+7 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+7, cStartNew, cEndNew);
3631:       for (p = 0; p < 4; ++p) {
3632:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
3633:       }
3634: #endif
3635:     }
3636:     /* Split faces have 3 edges and the same cells as the parent */
3637:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
3638:     PetscMalloc1(2 + maxSupportSize*3, &supportRef);
3639:     for (f = fStart; f < fEnd; ++f) {
3640:       const PetscInt  newp = fStartNew + (f - fStart)*4;
3641:       const PetscInt *cone, *ornt, *support;
3642:       PetscInt        coneNew[3], orntNew[3], coneSize, supportSize, s;

3644:       DMPlexGetCone(dm, f, &cone);
3645:       DMPlexGetConeOrientation(dm, f, &ornt);
3646:       /* A triangle */
3647:       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
3648:       orntNew[0] = ornt[0];
3649:       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
3650:       orntNew[1] = -2;
3651:       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
3652:       orntNew[2] = ornt[2];
3653:       DMPlexSetCone(rdm, newp+0, coneNew);
3654:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
3655: #if defined(PETSC_USE_DEBUG)
3656:       if ((newp+0 < fStartNew) || (newp+0 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+0, fStartNew, fEndNew);
3657:       for (p = 0; p < 3; ++p) {
3658:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3659:       }
3660: #endif
3661:       /* B triangle */
3662:       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
3663:       orntNew[0] = ornt[0];
3664:       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
3665:       orntNew[1] = ornt[1];
3666:       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
3667:       orntNew[2] = -2;
3668:       DMPlexSetCone(rdm, newp+1, coneNew);
3669:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
3670: #if defined(PETSC_USE_DEBUG)
3671:       if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+1, fStartNew, fEndNew);
3672:       for (p = 0; p < 3; ++p) {
3673:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3674:       }
3675: #endif
3676:       /* C triangle */
3677:       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
3678:       orntNew[0] = -2;
3679:       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
3680:       orntNew[1] = ornt[1];
3681:       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
3682:       orntNew[2] = ornt[2];
3683:       DMPlexSetCone(rdm, newp+2, coneNew);
3684:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
3685: #if defined(PETSC_USE_DEBUG)
3686:       if ((newp+2 < fStartNew) || (newp+2 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+2, fStartNew, fEndNew);
3687:       for (p = 0; p < 3; ++p) {
3688:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3689:       }
3690: #endif
3691:       /* D triangle */
3692:       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
3693:       orntNew[0] = 0;
3694:       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
3695:       orntNew[1] = 0;
3696:       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
3697:       orntNew[2] = 0;
3698:       DMPlexSetCone(rdm, newp+3, coneNew);
3699:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3700: #if defined(PETSC_USE_DEBUG)
3701:       if ((newp+3 < fStartNew) || (newp+3 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+3, fStartNew, fEndNew);
3702:       for (p = 0; p < 3; ++p) {
3703:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3704:       }
3705: #endif
3706:       DMPlexGetSupportSize(dm, f, &supportSize);
3707:       DMPlexGetSupport(dm, f, &support);
3708:       for (r = 0; r < 4; ++r) {
3709:         for (s = 0; s < supportSize; ++s) {
3710:           PetscInt subf;
3711:           DMPlexGetConeSize(dm, support[s], &coneSize);
3712:           DMPlexGetCone(dm, support[s], &cone);
3713:           DMPlexGetConeOrientation(dm, support[s], &ornt);
3714:           for (c = 0; c < coneSize; ++c) {
3715:             if (cone[c] == f) break;
3716:           }
3717:           subf = GetTriSubfaceInverse_Static(ornt[c], r);
3718:           supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
3719:         }
3720:         DMPlexSetSupport(rdm, newp+r, supportRef);
3721: #if defined(PETSC_USE_DEBUG)
3722:         if ((newp+r < fStartNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+r, fStartNew, fEndNew);
3723:         for (p = 0; p < supportSize; ++p) {
3724:           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
3725:         }
3726: #endif
3727:       }
3728:     }
3729:     /* Interior faces have 3 edges and 2 cells */
3730:     for (c = cStart; c < cEnd; ++c) {
3731:       PetscInt        newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8;
3732:       const PetscInt *cone, *ornt;
3733:       PetscInt        coneNew[3], orntNew[3];
3734:       PetscInt        supportNew[2];

3736:       DMPlexGetCone(dm, c, &cone);
3737:       DMPlexGetConeOrientation(dm, c, &ornt);
3738:       /* Face A: {c, a, d} */
3739:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
3740:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
3741:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
3742:       orntNew[1] = ornt[1] < 0 ? -2 : 0;
3743:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 2);
3744:       orntNew[2] = ornt[2] < 0 ? -2 : 0;
3745:       DMPlexSetCone(rdm, newp, coneNew);
3746:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3747: #if defined(PETSC_USE_DEBUG)
3748:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3749:       for (p = 0; p < 3; ++p) {
3750:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3751:       }
3752: #endif
3753:       supportNew[0] = (c - cStart)*8 + 0;
3754:       supportNew[1] = (c - cStart)*8 + 0+4;
3755:       DMPlexSetSupport(rdm, newp, supportNew);
3756: #if defined(PETSC_USE_DEBUG)
3757:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3758:       for (p = 0; p < 2; ++p) {
3759:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3760:       }
3761: #endif
3762:       ++newp;
3763:       /* Face B: {a, b, e} */
3764:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
3765:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
3766:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 0);
3767:       orntNew[1] = ornt[3] < 0 ? -2 : 0;
3768:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
3769:       orntNew[2] = ornt[1] < 0 ? -2 : 0;
3770:       DMPlexSetCone(rdm, newp, coneNew);
3771:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3772: #if defined(PETSC_USE_DEBUG)
3773:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3774:       for (p = 0; p < 3; ++p) {
3775:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3776:       }
3777: #endif
3778:       supportNew[0] = (c - cStart)*8 + 1;
3779:       supportNew[1] = (c - cStart)*8 + 1+4;
3780:       DMPlexSetSupport(rdm, newp, supportNew);
3781: #if defined(PETSC_USE_DEBUG)
3782:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3783:       for (p = 0; p < 2; ++p) {
3784:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3785:       }
3786: #endif
3787:       ++newp;
3788:       /* Face C: {c, f, b} */
3789:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
3790:       orntNew[0] = ornt[2] < 0 ? -2 : 0;
3791:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
3792:       orntNew[1] = ornt[3] < 0 ? -2 : 0;
3793:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 1);
3794:       orntNew[2] = ornt[0] < 0 ? -2 : 0;
3795:       DMPlexSetCone(rdm, newp, coneNew);
3796:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3797: #if defined(PETSC_USE_DEBUG)
3798:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3799:       for (p = 0; p < 3; ++p) {
3800:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3801:       }
3802: #endif
3803:       supportNew[0] = (c - cStart)*8 + 2;
3804:       supportNew[1] = (c - cStart)*8 + 2+4;
3805:       DMPlexSetSupport(rdm, newp, supportNew);
3806: #if defined(PETSC_USE_DEBUG)
3807:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3808:       for (p = 0; p < 2; ++p) {
3809:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3810:       }
3811: #endif
3812:       ++newp;
3813:       /* Face D: {d, e, f} */
3814:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 0);
3815:       orntNew[0] = ornt[1] < 0 ? -2 : 0;
3816:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
3817:       orntNew[1] = ornt[3] < 0 ? -2 : 0;
3818:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
3819:       orntNew[2] = ornt[2] < 0 ? -2 : 0;
3820:       DMPlexSetCone(rdm, newp, coneNew);
3821:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3822: #if defined(PETSC_USE_DEBUG)
3823:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3824:       for (p = 0; p < 3; ++p) {
3825:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3826:       }
3827: #endif
3828:       supportNew[0] = (c - cStart)*8 + 3;
3829:       supportNew[1] = (c - cStart)*8 + 3+4;
3830:       DMPlexSetSupport(rdm, newp, supportNew);
3831: #if defined(PETSC_USE_DEBUG)
3832:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3833:       for (p = 0; p < 2; ++p) {
3834:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3835:       }
3836: #endif
3837:       ++newp;
3838:       /* Face E: {d, f, a} */
3839:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
3840:       orntNew[0] = ornt[2] < 0 ? 0 : -2;
3841:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3842:       orntNew[1] = -2;
3843:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
3844:       orntNew[2] = ornt[1] < 0 ? -2 : 0;
3845:       DMPlexSetCone(rdm, newp, coneNew);
3846:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3847: #if defined(PETSC_USE_DEBUG)
3848:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3849:       for (p = 0; p < 3; ++p) {
3850:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3851:       }
3852: #endif
3853:       supportNew[0] = (c - cStart)*8 + 0+4;
3854:       supportNew[1] = (c - cStart)*8 + 3+4;
3855:       DMPlexSetSupport(rdm, newp, supportNew);
3856: #if defined(PETSC_USE_DEBUG)
3857:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3858:       for (p = 0; p < 2; ++p) {
3859:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3860:       }
3861: #endif
3862:       ++newp;
3863:       /* Face F: {c, a, f} */
3864:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
3865:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
3866:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3867:       orntNew[1] = 0;
3868:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
3869:       orntNew[2] = ornt[2] < 0 ? 0 : -2;
3870:       DMPlexSetCone(rdm, newp, coneNew);
3871:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3872: #if defined(PETSC_USE_DEBUG)
3873:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3874:       for (p = 0; p < 3; ++p) {
3875:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3876:       }
3877: #endif
3878:       supportNew[0] = (c - cStart)*8 + 0+4;
3879:       supportNew[1] = (c - cStart)*8 + 2+4;
3880:       DMPlexSetSupport(rdm, newp, supportNew);
3881: #if defined(PETSC_USE_DEBUG)
3882:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3883:       for (p = 0; p < 2; ++p) {
3884:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3885:       }
3886: #endif
3887:       ++newp;
3888:       /* Face G: {e, a, f} */
3889:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
3890:       orntNew[0] = ornt[1] < 0 ? -2 : 0;
3891:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3892:       orntNew[1] = 0;
3893:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
3894:       orntNew[2] = ornt[3] < 0 ? 0 : -2;
3895:       DMPlexSetCone(rdm, newp, coneNew);
3896:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3897: #if defined(PETSC_USE_DEBUG)
3898:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3899:       for (p = 0; p < 3; ++p) {
3900:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3901:       }
3902: #endif
3903:       supportNew[0] = (c - cStart)*8 + 1+4;
3904:       supportNew[1] = (c - cStart)*8 + 3+4;
3905:       DMPlexSetSupport(rdm, newp, supportNew);
3906: #if defined(PETSC_USE_DEBUG)
3907:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3908:       for (p = 0; p < 2; ++p) {
3909:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3910:       }
3911: #endif
3912:       ++newp;
3913:       /* Face H: {a, b, f} */
3914:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
3915:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
3916:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
3917:       orntNew[1] = ornt[3] < 0 ? 0 : -2;
3918:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3919:       orntNew[2] = -2;
3920:       DMPlexSetCone(rdm, newp, coneNew);
3921:       DMPlexSetConeOrientation(rdm, newp, orntNew);
3922: #if defined(PETSC_USE_DEBUG)
3923:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3924:       for (p = 0; p < 3; ++p) {
3925:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
3926:       }
3927: #endif
3928:       supportNew[0] = (c - cStart)*8 + 1+4;
3929:       supportNew[1] = (c - cStart)*8 + 2+4;
3930:       DMPlexSetSupport(rdm, newp, supportNew);
3931: #if defined(PETSC_USE_DEBUG)
3932:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
3933:       for (p = 0; p < 2; ++p) {
3934:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
3935:       }
3936: #endif
3937:       ++newp;
3938:     }
3939:     /* Split Edges have 2 vertices and the same faces as the parent */
3940:     for (e = eStart; e < eEnd; ++e) {
3941:       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);

3943:       for (r = 0; r < 2; ++r) {
3944:         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
3945:         const PetscInt *cone, *ornt, *support;
3946:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

3948:         DMPlexGetCone(dm, e, &cone);
3949:         coneNew[0]       = vStartNew + (cone[0] - vStart);
3950:         coneNew[1]       = vStartNew + (cone[1] - vStart);
3951:         coneNew[(r+1)%2] = newv;
3952:         DMPlexSetCone(rdm, newp, coneNew);
3953: #if defined(PETSC_USE_DEBUG)
3954:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
3955:         for (p = 0; p < 2; ++p) {
3956:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
3957:         }
3958: #endif
3959:         DMPlexGetSupportSize(dm, e, &supportSize);
3960:         DMPlexGetSupport(dm, e, &support);
3961:         for (s = 0; s < supportSize; ++s) {
3962:           DMPlexGetConeSize(dm, support[s], &coneSize);
3963:           DMPlexGetCone(dm, support[s], &cone);
3964:           DMPlexGetConeOrientation(dm, support[s], &ornt);
3965:           for (c = 0; c < coneSize; ++c) {
3966:             if (cone[c] == e) break;
3967:           }
3968:           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
3969:         }
3970:         DMPlexSetSupport(rdm, newp, supportRef);
3971: #if defined(PETSC_USE_DEBUG)
3972:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
3973:         for (p = 0; p < supportSize; ++p) {
3974:           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
3975:         }
3976: #endif
3977:       }
3978:     }
3979:     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
3980:     for (f = fStart; f < fEnd; ++f) {
3981:       const PetscInt *cone, *ornt, *support;
3982:       PetscInt        coneSize, supportSize, s;

3984:       DMPlexGetSupportSize(dm, f, &supportSize);
3985:       DMPlexGetSupport(dm, f, &support);
3986:       for (r = 0; r < 3; ++r) {
3987:         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
3988:         PetscInt        coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
3989:         PetscInt        fint[24] = { 1,  7, -1, -1,  0,  5,
3990:                                     -1, -1,  1,  6,  0,  4,
3991:                                      2,  5,  3,  4, -1, -1,
3992:                                     -1, -1,  3,  6,  2,  7};

3994:         DMPlexGetCone(dm, f, &cone);
3995:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
3996:         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
3997:         DMPlexSetCone(rdm, newp, coneNew);
3998: #if defined(PETSC_USE_DEBUG)
3999:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
4000:         for (p = 0; p < 2; ++p) {
4001:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
4002:         }
4003: #endif
4004:         supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
4005:         supportRef[1] = fStartNew + (f - fStart)*4 + 3;
4006:         for (s = 0; s < supportSize; ++s) {
4007:           DMPlexGetConeSize(dm, support[s], &coneSize);
4008:           DMPlexGetCone(dm, support[s], &cone);
4009:           DMPlexGetConeOrientation(dm, support[s], &ornt);
4010:           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
4011:           /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
4012:           er = GetTriMidEdgeInverse_Static(ornt[c], r);
4013:           if (er == eint[c]) {
4014:             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
4015:           } else {
4016:             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
4017:             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
4018:           }
4019:         }
4020:         DMPlexSetSupport(rdm, newp, supportRef);
4021: #if defined(PETSC_USE_DEBUG)
4022:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
4023:         for (p = 0; p < intFaces; ++p) {
4024:           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
4025:         }
4026: #endif
4027:       }
4028:     }
4029:     /* Interior edges have 2 vertices and 4 faces */
4030:     for (c = cStart; c < cEnd; ++c) {
4031:       const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
4032:       const PetscInt *cone, *ornt, *fcone;
4033:       PetscInt        coneNew[2], supportNew[4], find;

4035:       DMPlexGetCone(dm, c, &cone);
4036:       DMPlexGetConeOrientation(dm, c, &ornt);
4037:       DMPlexGetCone(dm, cone[0], &fcone);
4038:       find = GetTriEdge_Static(ornt[0], 0);
4039:       coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
4040:       DMPlexGetCone(dm, cone[2], &fcone);
4041:       find = GetTriEdge_Static(ornt[2], 1);
4042:       coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
4043:       DMPlexSetCone(rdm, newp, coneNew);
4044: #if defined(PETSC_USE_DEBUG)
4045:       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
4046:       for (p = 0; p < 2; ++p) {
4047:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
4048:       }
4049: #endif
4050:       supportNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
4051:       supportNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
4052:       supportNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
4053:       supportNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
4054:       DMPlexSetSupport(rdm, newp, supportNew);
4055: #if defined(PETSC_USE_DEBUG)
4056:       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
4057:       for (p = 0; p < 4; ++p) {
4058:         if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fEndNew);
4059:       }
4060: #endif
4061:     }
4062:     /* Old vertices have identical supports */
4063:     for (v = vStart; v < vEnd; ++v) {
4064:       const PetscInt  newp = vStartNew + (v - vStart);
4065:       const PetscInt *support, *cone;
4066:       PetscInt        size, s;

4068:       DMPlexGetSupportSize(dm, v, &size);
4069:       DMPlexGetSupport(dm, v, &support);
4070:       for (s = 0; s < size; ++s) {
4071:         PetscInt r = 0;

4073:         DMPlexGetCone(dm, support[s], &cone);
4074:         if (cone[1] == v) r = 1;
4075:         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
4076:       }
4077:       DMPlexSetSupport(rdm, newp, supportRef);
4078: #if defined(PETSC_USE_DEBUG)
4079:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
4080:       for (p = 0; p < size; ++p) {
4081:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
4082:       }
4083: #endif
4084:     }
4085:     /* Edge vertices have 2 + face*2 + 0/1 supports */
4086:     for (e = eStart; e < eEnd; ++e) {
4087:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
4088:       const PetscInt *cone, *support;
4089:       PetscInt       *star = NULL, starSize, cellSize = 0, coneSize, size, s;

4091:       DMPlexGetSupportSize(dm, e, &size);
4092:       DMPlexGetSupport(dm, e, &support);
4093:       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
4094:       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
4095:       for (s = 0; s < size; ++s) {
4096:         PetscInt r = 0;

4098:         DMPlexGetConeSize(dm, support[s], &coneSize);
4099:         DMPlexGetCone(dm, support[s], &cone);
4100:         for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
4101:         supportRef[2+s*2+0] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
4102:         supportRef[2+s*2+1] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
4103:       }
4104:       DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
4105:       for (s = 0; s < starSize*2; s += 2) {
4106:         const PetscInt *cone, *ornt;
4107:         PetscInt        e01, e23;

4109:         if ((star[s] >= cStart) && (star[s] < cEnd)) {
4110:           /* Check edge 0-1 */
4111:           DMPlexGetCone(dm, star[s], &cone);
4112:           DMPlexGetConeOrientation(dm, star[s], &ornt);
4113:           DMPlexGetCone(dm, cone[0], &cone);
4114:           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
4115:           /* Check edge 2-3 */
4116:           DMPlexGetCone(dm, star[s], &cone);
4117:           DMPlexGetConeOrientation(dm, star[s], &ornt);
4118:           DMPlexGetCone(dm, cone[2], &cone);
4119:           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
4120:           if ((e01 == e) || (e23 == e)) {supportRef[2+size*2+cellSize++] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (star[s] - cStart);}
4121:         }
4122:       }
4123:       DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
4124:       DMPlexSetSupport(rdm, newp, supportRef);
4125: #if defined(PETSC_USE_DEBUG)
4126:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
4127:       for (p = 0; p < 2+size*2+cellSize; ++p) {
4128:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
4129:       }
4130: #endif
4131:     }
4132:     PetscFree(supportRef);
4133:     DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
4134:     break;
4135:   case REFINER_HYBRID_SIMPLEX_3D:
4136:     DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);
4137:     /* Interior cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
4138:     DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
4139:     for (c = cStart; c < cMax; ++c) {
4140:       const PetscInt  newp = cStartNew + (c - cStart)*8;
4141:       const PetscInt *cone, *ornt;
4142:       PetscInt        coneNew[4], orntNew[4];

4144:       DMPlexGetCone(dm, c, &cone);
4145:       DMPlexGetConeOrientation(dm, c, &ornt);
4146:       /* A tetrahedron: {0, a, c, d} */
4147:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
4148:       orntNew[0] = ornt[0];
4149:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
4150:       orntNew[1] = ornt[1];
4151:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
4152:       orntNew[2] = ornt[2];
4153:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 0;
4154:       orntNew[3] = 0;
4155:       DMPlexSetCone(rdm, newp+0, coneNew);
4156:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
4157: #if defined(PETSC_USE_DEBUG)
4158:       if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cMaxNew);
4159:       for (p = 0; p < 4; ++p) {
4160:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4161:       }
4162: #endif
4163:       /* B tetrahedron: {a, 1, b, e} */
4164:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
4165:       orntNew[0] = ornt[0];
4166:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
4167:       orntNew[1] = ornt[1];
4168:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 1;
4169:       orntNew[2] = 0;
4170:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
4171:       orntNew[3] = ornt[3];
4172:       DMPlexSetCone(rdm, newp+1, coneNew);
4173:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
4174: #if defined(PETSC_USE_DEBUG)
4175:       if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cMaxNew);
4176:       for (p = 0; p < 4; ++p) {
4177:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4178:       }
4179: #endif
4180:       /* C tetrahedron: {c, b, 2, f} */
4181:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
4182:       orntNew[0] = ornt[0];
4183:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 2;
4184:       orntNew[1] = 0;
4185:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
4186:       orntNew[2] = ornt[2];
4187:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
4188:       orntNew[3] = ornt[3];
4189:       DMPlexSetCone(rdm, newp+2, coneNew);
4190:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
4191: #if defined(PETSC_USE_DEBUG)
4192:       if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cMaxNew);
4193:       for (p = 0; p < 4; ++p) {
4194:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4195:       }
4196: #endif
4197:       /* D tetrahedron: {d, e, f, 3} */
4198:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 3;
4199:       orntNew[0] = 0;
4200:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
4201:       orntNew[1] = ornt[1];
4202:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
4203:       orntNew[2] = ornt[2];
4204:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
4205:       orntNew[3] = ornt[3];
4206:       DMPlexSetCone(rdm, newp+3, coneNew);
4207:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
4208: #if defined(PETSC_USE_DEBUG)
4209:       if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cMaxNew);
4210:       for (p = 0; p < 4; ++p) {
4211:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4212:       }
4213: #endif
4214:       /* A' tetrahedron: {d, a, c, f} */
4215:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 0;
4216:       orntNew[0] = -3;
4217:       coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
4218:       orntNew[1] = ornt[2] < 0 ? -(GetTriMidEdge_Static(ornt[2], 0)+1) : GetTriMidEdge_Static(ornt[2], 0);
4219:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 5;
4220:       orntNew[2] = 0;
4221:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 4;
4222:       orntNew[3] = 2;
4223:       DMPlexSetCone(rdm, newp+4, coneNew);
4224:       DMPlexSetConeOrientation(rdm, newp+4, orntNew);
4225: #if defined(PETSC_USE_DEBUG)
4226:       if ((newp+4 < cStartNew) || (newp+4 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+4, cStartNew, cMaxNew);
4227:       for (p = 0; p < 4; ++p) {
4228:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4229:       }
4230: #endif
4231:       /* B' tetrahedron: {e, b, a, f} */
4232:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 1;
4233:       orntNew[0] = -3;
4234:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 6;
4235:       orntNew[1] = 1;
4236:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 7;
4237:       orntNew[2] = 0;
4238:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + 3;
4239:       orntNew[3] = ornt[3] < 0 ? -(GetTriMidEdge_Static(ornt[3], 0)+1) : GetTriMidEdge_Static(ornt[3], 0);
4240:       DMPlexSetCone(rdm, newp+5, coneNew);
4241:       DMPlexSetConeOrientation(rdm, newp+5, orntNew);
4242: #if defined(PETSC_USE_DEBUG)
4243:       if ((newp+5 < cStartNew) || (newp+5 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+5, cStartNew, cMaxNew);
4244:       for (p = 0; p < 4; ++p) {
4245:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4246:       }
4247: #endif
4248:       /* C' tetrahedron: {b, f, c, a} */
4249:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 2;
4250:       orntNew[0] = -3;
4251:       coneNew[1] = fStartNew + (cone[0] - fStart)*4 + 3;
4252:       orntNew[1] = ornt[0] < 0 ? -(GetTriMidEdge_Static(ornt[0], 2)+1) : GetTriMidEdge_Static(ornt[0], 2);
4253:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 5;
4254:       orntNew[2] = -3;
4255:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 7;
4256:       orntNew[3] = -2;
4257:       DMPlexSetCone(rdm, newp+6, coneNew);
4258:       DMPlexSetConeOrientation(rdm, newp+6, orntNew);
4259: #if defined(PETSC_USE_DEBUG)
4260:       if ((newp+6 < cStartNew) || (newp+6 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+6, cStartNew, cMaxNew);
4261:       for (p = 0; p < 4; ++p) {
4262:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4263:       }
4264: #endif
4265:       /* D' tetrahedron: {f, e, d, a} */
4266:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 3;
4267:       orntNew[0] = -3;
4268:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 4;
4269:       orntNew[1] = -3;
4270:       coneNew[2] = fStartNew + (cone[1] - fStart)*4 + 3;
4271:       orntNew[2] = ornt[1] < 0 ? -(GetTriMidEdge_Static(ornt[1], 0)+1) : GetTriMidEdge_Static(ornt[1], 0);
4272:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*8 + 6;
4273:       orntNew[3] = -3;
4274:       DMPlexSetCone(rdm, newp+7, coneNew);
4275:       DMPlexSetConeOrientation(rdm, newp+7, orntNew);
4276: #if defined(PETSC_USE_DEBUG)
4277:       if ((newp+7 < cStartNew) || (newp+7 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+7, cStartNew, cMaxNew);
4278:       for (p = 0; p < 4; ++p) {
4279:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4280:       }
4281: #endif
4282:     }
4283:     /* Hybrid cells have 5 faces */
4284:     for (c = cMax; c < cEnd; ++c) {
4285:       const PetscInt  newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4;
4286:       const PetscInt *cone, *ornt, *fornt;
4287:       PetscInt        coneNew[5], orntNew[5], o, of, i;

4289:       DMPlexGetCone(dm, c, &cone);
4290:       DMPlexGetConeOrientation(dm, c, &ornt);
4291:       DMPlexGetConeOrientation(dm, cone[0], &fornt);
4292:       o = ornt[0] < 0 ? -1 : 1;
4293:       for (r = 0; r < 3; ++r) {
4294:         coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], r);
4295:         orntNew[0] = ornt[0];
4296:         coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], r);
4297:         orntNew[1] = ornt[1];
4298:         of = fornt[GetTriEdge_Static(ornt[0], r)]       < 0 ? -1 : 1;
4299:         i  = GetTriEdgeInverse_Static(ornt[0], r)       + 2;
4300:         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], r)]       - fMax)*2 + (o*of < 0 ? 1 : 0);
4301:         orntNew[i] = 0;
4302:         i  = GetTriEdgeInverse_Static(ornt[0], (r+1)%3) + 2;
4303:         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + GetTriSubface_Static(ornt[0], r);
4304:         orntNew[i] = 0;
4305:         of = fornt[GetTriEdge_Static(ornt[0], (r+2)%3)] < 0 ? -1 : 1;
4306:         i  = GetTriEdgeInverse_Static(ornt[0], (r+2)%3) + 2;
4307:         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], (r+2)%3)] - fMax)*2 + (o*of < 0 ? 0 : 1);
4308:         orntNew[i] = 0;
4309:         DMPlexSetCone(rdm, newp+r, coneNew);
4310:         DMPlexSetConeOrientation(rdm, newp+r, orntNew);
4311: #if defined(PETSC_USE_DEBUG)
4312:         if ((newp+r < cMaxNew) || (newp+r >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", newp+r, cMaxNew, cEndNew);
4313:         for (p = 0; p < 2; ++p) {
4314:           if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4315:         }
4316:         for (p = 2; p < 5; ++p) {
4317:           if ((coneNew[p] < fMaxNew)   || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", coneNew[p], fMaxNew, fEndNew);
4318:         }
4319: #endif
4320:       }
4321:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + 3;
4322:       orntNew[0] = 0;
4323:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + 3;
4324:       orntNew[1] = 0;
4325:       coneNew[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;
4326:       orntNew[2] = 0;
4327:       coneNew[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;
4328:       orntNew[3] = 0;
4329:       coneNew[4] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;
4330:       orntNew[4] = 0;
4331:       DMPlexSetCone(rdm, newp+3, coneNew);
4332:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
4333: #if defined(PETSC_USE_DEBUG)
4334:       if ((newp+3 < cMaxNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", newp+3, cMaxNew, cEndNew);
4335:       for (p = 0; p < 2; ++p) {
4336:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
4337:       }
4338:       for (p = 2; p < 5; ++p) {
4339:         if ((coneNew[p] < fMaxNew)   || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", coneNew[p], fMaxNew, fEndNew);
4340:       }
4341: #endif
4342:     }
4343:     /* Split faces have 3 edges and the same cells as the parent */
4344:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
4345:     PetscMalloc1(2 + maxSupportSize*2, &supportRef);
4346:     for (f = fStart; f < fMax; ++f) {
4347:       const PetscInt  newp = fStartNew + (f - fStart)*4;
4348:       const PetscInt *cone, *ornt, *support;
4349:       PetscInt        coneNew[3], orntNew[3], coneSize, supportSize, s;

4351:       DMPlexGetCone(dm, f, &cone);
4352:       DMPlexGetConeOrientation(dm, f, &ornt);
4353:       /* A triangle */
4354:       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
4355:       orntNew[0] = ornt[0];
4356:       coneNew[1] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
4357:       orntNew[1] = -2;
4358:       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
4359:       orntNew[2] = ornt[2];
4360:       DMPlexSetCone(rdm, newp+0, coneNew);
4361:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
4362: #if defined(PETSC_USE_DEBUG)
4363:       if ((newp+0 < fStartNew) || (newp+0 >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+0, fStartNew, fMaxNew);
4364:       for (p = 0; p < 3; ++p) {
4365:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4366:       }
4367: #endif
4368:       /* B triangle */
4369:       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
4370:       orntNew[0] = ornt[0];
4371:       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
4372:       orntNew[1] = ornt[1];
4373:       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
4374:       orntNew[2] = -2;
4375:       DMPlexSetCone(rdm, newp+1, coneNew);
4376:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
4377: #if defined(PETSC_USE_DEBUG)
4378:       if ((newp+1 < fStartNew) || (newp+1 >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+1, fStartNew, fMaxNew);
4379:       for (p = 0; p < 3; ++p) {
4380:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4381:       }
4382: #endif
4383:       /* C triangle */
4384:       coneNew[0] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
4385:       orntNew[0] = -2;
4386:       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
4387:       orntNew[1] = ornt[1];
4388:       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
4389:       orntNew[2] = ornt[2];
4390:       DMPlexSetCone(rdm, newp+2, coneNew);
4391:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
4392: #if defined(PETSC_USE_DEBUG)
4393:       if ((newp+2 < fStartNew) || (newp+2 >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+2, fStartNew, fMaxNew);
4394:       for (p = 0; p < 3; ++p) {
4395:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4396:       }
4397: #endif
4398:       /* D triangle */
4399:       coneNew[0] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
4400:       orntNew[0] = 0;
4401:       coneNew[1] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
4402:       orntNew[1] = 0;
4403:       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
4404:       orntNew[2] = 0;
4405:       DMPlexSetCone(rdm, newp+3, coneNew);
4406:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
4407: #if defined(PETSC_USE_DEBUG)
4408:       if ((newp+3 < fStartNew) || (newp+3 >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+3, fStartNew, fMaxNew);
4409:       for (p = 0; p < 3; ++p) {
4410:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4411:       }
4412: #endif
4413:       DMPlexGetSupportSize(dm, f, &supportSize);
4414:       DMPlexGetSupport(dm, f, &support);
4415:       for (r = 0; r < 4; ++r) {
4416:         for (s = 0; s < supportSize; ++s) {
4417:           PetscInt subf;
4418:           DMPlexGetConeSize(dm, support[s], &coneSize);
4419:           DMPlexGetCone(dm, support[s], &cone);
4420:           DMPlexGetConeOrientation(dm, support[s], &ornt);
4421:           for (c = 0; c < coneSize; ++c) {
4422:             if (cone[c] == f) break;
4423:           }
4424:           subf = GetTriSubfaceInverse_Static(ornt[c], r);
4425:           if (support[s] < cMax) {
4426:             supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
4427:           } else {
4428:             supportRef[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (r==3 ? r : subf);
4429:           }
4430:         }
4431:         DMPlexSetSupport(rdm, newp+r, supportRef);
4432: #if defined(PETSC_USE_DEBUG)
4433:         if ((newp+r < fStartNew) || (newp+r >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+r, fStartNew, fMaxNew);
4434:         for (p = 0; p < supportSize; ++p) {
4435:           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior or hybrid cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
4436:         }
4437: #endif
4438:       }
4439:     }
4440:     /* Interior cell faces have 3 edges and 2 cells */
4441:     for (c = cStart; c < cMax; ++c) {
4442:       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8;
4443:       const PetscInt *cone, *ornt;
4444:       PetscInt        coneNew[3], orntNew[3];
4445:       PetscInt        supportNew[2];

4447:       DMPlexGetCone(dm, c, &cone);
4448:       DMPlexGetConeOrientation(dm, c, &ornt);
4449:       /* Face A: {c, a, d} */
4450:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
4451:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
4452:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
4453:       orntNew[1] = ornt[1] < 0 ? -2 : 0;
4454:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 2);
4455:       orntNew[2] = ornt[2] < 0 ? -2 : 0;
4456:       DMPlexSetCone(rdm, newp, coneNew);
4457:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4458: #if defined(PETSC_USE_DEBUG)
4459:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4460:       for (p = 0; p < 3; ++p) {
4461:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4462:       }
4463: #endif
4464:       supportNew[0] = (c - cStart)*8 + 0;
4465:       supportNew[1] = (c - cStart)*8 + 0+4;
4466:       DMPlexSetSupport(rdm, newp, supportNew);
4467: #if defined(PETSC_USE_DEBUG)
4468:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4469:       for (p = 0; p < 2; ++p) {
4470:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4471:       }
4472: #endif
4473:       ++newp;
4474:       /* Face B: {a, b, e} */
4475:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
4476:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
4477:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 0);
4478:       orntNew[1] = ornt[3] < 0 ? -2 : 0;
4479:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
4480:       orntNew[2] = ornt[1] < 0 ? -2 : 0;
4481:       DMPlexSetCone(rdm, newp, coneNew);
4482:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4483: #if defined(PETSC_USE_DEBUG)
4484:       if ((newp+1 < fStartNew) || (newp+1 >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+1, fStartNew, fMaxNew);
4485:       for (p = 0; p < 3; ++p) {
4486:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4487:       }
4488: #endif
4489:       supportNew[0] = (c - cStart)*8 + 1;
4490:       supportNew[1] = (c - cStart)*8 + 1+4;
4491:       DMPlexSetSupport(rdm, newp, supportNew);
4492: #if defined(PETSC_USE_DEBUG)
4493:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4494:       for (p = 0; p < 2; ++p) {
4495:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4496:       }
4497: #endif
4498:       ++newp;
4499:       /* Face C: {c, f, b} */
4500:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
4501:       orntNew[0] = ornt[2] < 0 ? -2 : 0;
4502:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
4503:       orntNew[1] = ornt[3] < 0 ? -2 : 0;
4504:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 1);
4505:       orntNew[2] = ornt[0] < 0 ? -2 : 0;
4506:       DMPlexSetCone(rdm, newp, coneNew);
4507:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4508: #if defined(PETSC_USE_DEBUG)
4509:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4510:       for (p = 0; p < 3; ++p) {
4511:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4512:       }
4513: #endif
4514:       supportNew[0] = (c - cStart)*8 + 2;
4515:       supportNew[1] = (c - cStart)*8 + 2+4;
4516:       DMPlexSetSupport(rdm, newp, supportNew);
4517: #if defined(PETSC_USE_DEBUG)
4518:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4519:       for (p = 0; p < 2; ++p) {
4520:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4521:       }
4522: #endif
4523:       ++newp;
4524:       /* Face D: {d, e, f} */
4525:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 0);
4526:       orntNew[0] = ornt[1] < 0 ? -2 : 0;
4527:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
4528:       orntNew[1] = ornt[3] < 0 ? -2 : 0;
4529:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
4530:       orntNew[2] = ornt[2] < 0 ? -2 : 0;
4531:       DMPlexSetCone(rdm, newp, coneNew);
4532:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4533: #if defined(PETSC_USE_DEBUG)
4534:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4535:       for (p = 0; p < 3; ++p) {
4536:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4537:       }
4538: #endif
4539:       supportNew[0] = (c - cStart)*8 + 3;
4540:       supportNew[1] = (c - cStart)*8 + 3+4;
4541:       DMPlexSetSupport(rdm, newp, supportNew);
4542: #if defined(PETSC_USE_DEBUG)
4543:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4544:       for (p = 0; p < 2; ++p) {
4545:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4546:       }
4547: #endif
4548:       ++newp;
4549:       /* Face E: {d, f, a} */
4550:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
4551:       orntNew[0] = ornt[2] < 0 ? 0 : -2;
4552:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
4553:       orntNew[1] = -2;
4554:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
4555:       orntNew[2] = ornt[1] < 0 ? -2 : 0;
4556:       DMPlexSetCone(rdm, newp, coneNew);
4557:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4558: #if defined(PETSC_USE_DEBUG)
4559:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4560:       for (p = 0; p < 3; ++p) {
4561:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4562:       }
4563: #endif
4564:       supportNew[0] = (c - cStart)*8 + 0+4;
4565:       supportNew[1] = (c - cStart)*8 + 3+4;
4566:       DMPlexSetSupport(rdm, newp, supportNew);
4567: #if defined(PETSC_USE_DEBUG)
4568:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4569:       for (p = 0; p < 2; ++p) {
4570:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4571:       }
4572: #endif
4573:       ++newp;
4574:       /* Face F: {c, a, f} */
4575:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
4576:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
4577:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
4578:       orntNew[1] = 0;
4579:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
4580:       orntNew[2] = ornt[2] < 0 ? 0 : -2;
4581:       DMPlexSetCone(rdm, newp, coneNew);
4582:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4583: #if defined(PETSC_USE_DEBUG)
4584:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4585:       for (p = 0; p < 3; ++p) {
4586:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4587:       }
4588: #endif
4589:       supportNew[0] = (c - cStart)*8 + 0+4;
4590:       supportNew[1] = (c - cStart)*8 + 2+4;
4591:       DMPlexSetSupport(rdm, newp, supportNew);
4592: #if defined(PETSC_USE_DEBUG)
4593:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4594:       for (p = 0; p < 2; ++p) {
4595:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4596:       }
4597: #endif
4598:       ++newp;
4599:       /* Face G: {e, a, f} */
4600:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
4601:       orntNew[0] = ornt[1] < 0 ? -2 : 0;
4602:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
4603:       orntNew[1] = 0;
4604:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
4605:       orntNew[2] = ornt[3] < 0 ? 0 : -2;
4606:       DMPlexSetCone(rdm, newp, coneNew);
4607:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4608: #if defined(PETSC_USE_DEBUG)
4609:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4610:       for (p = 0; p < 3; ++p) {
4611:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4612:       }
4613: #endif
4614:       supportNew[0] = (c - cStart)*8 + 1+4;
4615:       supportNew[1] = (c - cStart)*8 + 3+4;
4616:       DMPlexSetSupport(rdm, newp, supportNew);
4617: #if defined(PETSC_USE_DEBUG)
4618:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4619:       for (p = 0; p < 2; ++p) {
4620:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4621:       }
4622: #endif
4623:       ++newp;
4624:       /* Face H: {a, b, f} */
4625:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
4626:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
4627:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
4628:       orntNew[1] = ornt[3] < 0 ? 0 : -2;
4629:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
4630:       orntNew[2] = -2;
4631:       DMPlexSetCone(rdm, newp, coneNew);
4632:       DMPlexSetConeOrientation(rdm, newp, orntNew);
4633: #if defined(PETSC_USE_DEBUG)
4634:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4635:       for (p = 0; p < 3; ++p) {
4636:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4637:       }
4638: #endif
4639:       supportNew[0] = (c - cStart)*8 + 1+4;
4640:       supportNew[1] = (c - cStart)*8 + 2+4;
4641:       DMPlexSetSupport(rdm, newp, supportNew);
4642: #if defined(PETSC_USE_DEBUG)
4643:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
4644:       for (p = 0; p < 2; ++p) {
4645:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
4646:       }
4647: #endif
4648:       ++newp;
4649:     }
4650:     /* Hybrid split faces have 4 edges and same cells */
4651:     for (f = fMax; f < fEnd; ++f) {
4652:       const PetscInt *cone, *ornt, *support;
4653:       PetscInt        coneNew[4], orntNew[4];
4654:       PetscInt        supportNew[2], size, s, c;

4656:       DMPlexGetCone(dm, f, &cone);
4657:       DMPlexGetConeOrientation(dm, f, &ornt);
4658:       DMPlexGetSupportSize(dm, f, &size);
4659:       DMPlexGetSupport(dm, f, &support);
4660:       for (r = 0; r < 2; ++r) {
4661:         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;

4663:         coneNew[0]   = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
4664:         orntNew[0]   = ornt[0];
4665:         coneNew[1]   = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
4666:         orntNew[1]   = ornt[1];
4667:         coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (cone[2+r] - eMax);
4668:         orntNew[2+r] = 0;
4669:         coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd      - eMax) + (f - fMax);
4670:         orntNew[3-r] = 0;
4671:         DMPlexSetCone(rdm, newp, coneNew);
4672:         DMPlexSetConeOrientation(rdm, newp, orntNew);
4673: #if defined(PETSC_USE_DEBUG)
4674:         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp, fMaxNew, fEndNew);
4675:         for (p = 0; p < 2; ++p) {
4676:           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4677:         }
4678:         for (p = 2; p < 4; ++p) {
4679:           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", coneNew[p], eMaxNew, eEndNew);
4680:         }
4681: #endif
4682:         for (s = 0; s < size; ++s) {
4683:           const PetscInt *coneCell, *orntCell, *fornt;
4684:           PetscInt        o, of;

4686:           DMPlexGetCone(dm, support[s], &coneCell);
4687:           DMPlexGetConeOrientation(dm, support[s], &orntCell);
4688:           o = orntCell[0] < 0 ? -1 : 1;
4689:           for (c = 2; c < 5; ++c) if (coneCell[c] == f) break;
4690:           if (c >= 5) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %D in cone of cell %D", f, support[s]);
4691:           DMPlexGetConeOrientation(dm, coneCell[0], &fornt);
4692:           of = fornt[c-2] < 0 ? -1 : 1;
4693:           supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetTriEdgeInverse_Static(orntCell[0], c-2) + (o*of < 0 ? 1-r : r))%3;
4694:         }
4695:         DMPlexSetSupport(rdm, newp, supportNew);
4696: #if defined(PETSC_USE_DEBUG)
4697:         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp, fMaxNew, fEndNew);
4698:         for (p = 0; p < size; ++p) {
4699:           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", supportNew[p], cMaxNew, cEndNew);
4700:         }
4701: #endif
4702:       }
4703:     }
4704:     /* Hybrid cell faces have 4 edges and 2 cells */
4705:     for (c = cMax; c < cEnd; ++c) {
4706:       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3;
4707:       const PetscInt *cone, *ornt;
4708:       PetscInt        coneNew[4], orntNew[4];
4709:       PetscInt        supportNew[2];

4711:       DMPlexGetCone(dm, c, &cone);
4712:       DMPlexGetConeOrientation(dm, c, &ornt);
4713:       for (r = 0; r < 3; ++r) {
4714:         coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + (r+2)%3;
4715:         orntNew[0] = 0;
4716:         coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + (r+2)%3;
4717:         orntNew[1] = 0;
4718:         coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+(r+2)%3] - fMax);
4719:         orntNew[2] = 0;
4720:         coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+r]       - fMax);
4721:         orntNew[3] = 0;
4722:         DMPlexSetCone(rdm, newp+r, coneNew);
4723:         DMPlexSetConeOrientation(rdm, newp+r, orntNew);
4724: #if defined(PETSC_USE_DEBUG)
4725:         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp+r, fMaxNew, fEndNew);
4726:         for (p = 0; p < 2; ++p) {
4727:           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
4728:         }
4729:         for (p = 2; p < 4; ++p) {
4730:           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", coneNew[p], eMaxNew, eEndNew);
4731:         }
4732: #endif
4733:         supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetTriSubface_Static(ornt[0], r);
4734:         supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + 3;
4735:         DMPlexSetSupport(rdm, newp+r, supportNew);
4736: #if defined(PETSC_USE_DEBUG)
4737:         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp+r, fMaxNew, fEndNew);
4738:         for (p = 0; p < 2; ++p) {
4739:           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", supportNew[p], cMaxNew, cEndNew);
4740:         }
4741: #endif
4742:       }
4743:     }
4744:     /* Interior split edges have 2 vertices and the same faces as the parent */
4745:     for (e = eStart; e < eMax; ++e) {
4746:       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);

4748:       for (r = 0; r < 2; ++r) {
4749:         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
4750:         const PetscInt *cone, *ornt, *support;
4751:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

4753:         DMPlexGetCone(dm, e, &cone);
4754:         coneNew[0]       = vStartNew + (cone[0] - vStart);
4755:         coneNew[1]       = vStartNew + (cone[1] - vStart);
4756:         coneNew[(r+1)%2] = newv;
4757:         DMPlexSetCone(rdm, newp, coneNew);
4758: #if defined(PETSC_USE_DEBUG)
4759:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
4760:         for (p = 0; p < 2; ++p) {
4761:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
4762:         }
4763: #endif
4764:         DMPlexGetSupportSize(dm, e, &supportSize);
4765:         DMPlexGetSupport(dm, e, &support);
4766:         for (s = 0; s < supportSize; ++s) {
4767:           DMPlexGetConeSize(dm, support[s], &coneSize);
4768:           DMPlexGetCone(dm, support[s], &cone);
4769:           DMPlexGetConeOrientation(dm, support[s], &ornt);
4770:           for (c = 0; c < coneSize; ++c) if (cone[c] == e) break;
4771:           if (support[s] < fMax) {
4772:             supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
4773:           } else {
4774:             supportRef[s] = fStartNew + (fMax       - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
4775:           }
4776:         }
4777:         DMPlexSetSupport(rdm, newp, supportRef);
4778: #if defined(PETSC_USE_DEBUG)
4779:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
4780:         for (p = 0; p < supportSize; ++p) {
4781:           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior or hybrid face [%D, %D)", supportRef[p], fStartNew, fEndNew);
4782:         }
4783: #endif
4784:       }
4785:     }
4786:     /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
4787:     for (f = fStart; f < fMax; ++f) {
4788:       const PetscInt *cone, *ornt, *support;
4789:       PetscInt        coneSize, supportSize, s;

4791:       DMPlexGetSupportSize(dm, f, &supportSize);
4792:       DMPlexGetSupport(dm, f, &support);
4793:       for (r = 0; r < 3; ++r) {
4794:         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
4795:         PetscInt        coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
4796:         PetscInt        fint[24] = { 1,  7, -1, -1,  0,  5,
4797:                                     -1, -1,  1,  6,  0,  4,
4798:                                      2,  5,  3,  4, -1, -1,
4799:                                     -1, -1,  3,  6,  2,  7};

4801:         DMPlexGetCone(dm, f, &cone);
4802:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
4803:         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
4804:         DMPlexSetCone(rdm, newp, coneNew);
4805: #if defined(PETSC_USE_DEBUG)
4806:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
4807:         for (p = 0; p < 2; ++p) {
4808:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
4809:         }
4810: #endif
4811:         supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
4812:         supportRef[1] = fStartNew + (f - fStart)*4 + 3;
4813:         for (s = 0; s < supportSize; ++s) {
4814:           DMPlexGetConeSize(dm, support[s], &coneSize);
4815:           DMPlexGetCone(dm, support[s], &cone);
4816:           DMPlexGetConeOrientation(dm, support[s], &ornt);
4817:           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
4818:           if (support[s] < cMax) {
4819:             /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
4820:             er = GetTriMidEdgeInverse_Static(ornt[c], r);
4821:             if (er == eint[c]) {
4822:               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
4823:             } else {
4824:               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
4825:               supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
4826:             }
4827:           } else {
4828:             supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (r + 1)%3;
4829:           }
4830:         }
4831:         DMPlexSetSupport(rdm, newp, supportRef);
4832: #if defined(PETSC_USE_DEBUG)
4833:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
4834:         for (p = 0; p < intFaces; ++p) {
4835:           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior or hybrid face [%D, %D)", supportRef[p], fStartNew, fEndNew);
4836:         }
4837: #endif
4838:       }
4839:     }
4840:     /* Interior cell edges have 2 vertices and 4 faces */
4841:     for (c = cStart; c < cMax; ++c) {
4842:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
4843:       const PetscInt *cone, *ornt, *fcone;
4844:       PetscInt        coneNew[2], supportNew[4], find;

4846:       DMPlexGetCone(dm, c, &cone);
4847:       DMPlexGetConeOrientation(dm, c, &ornt);
4848:       DMPlexGetCone(dm, cone[0], &fcone);
4849:       find = GetTriEdge_Static(ornt[0], 0);
4850:       coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
4851:       DMPlexGetCone(dm, cone[2], &fcone);
4852:       find = GetTriEdge_Static(ornt[2], 1);
4853:       coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
4854:       DMPlexSetCone(rdm, newp, coneNew);
4855: #if defined(PETSC_USE_DEBUG)
4856:       if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
4857:       for (p = 0; p < 2; ++p) {
4858:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
4859:       }
4860: #endif
4861:       supportNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
4862:       supportNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
4863:       supportNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
4864:       supportNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
4865:       DMPlexSetSupport(rdm, newp, supportNew);
4866: #if defined(PETSC_USE_DEBUG)
4867:       if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
4868:       for (p = 0; p < 4; ++p) {
4869:         if ((supportNew[p] < fStartNew) || (supportNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fMaxNew);
4870:       }
4871: #endif
4872:     }
4873:     /* Hybrid edges have two vertices and the same faces */
4874:     for (e = eMax; e < eEnd; ++e) {
4875:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
4876:       const PetscInt *cone, *support, *fcone;
4877:       PetscInt        coneNew[2], size, fsize, s;

4879:       DMPlexGetCone(dm, e, &cone);
4880:       DMPlexGetSupportSize(dm, e, &size);
4881:       DMPlexGetSupport(dm, e, &support);
4882:       coneNew[0] = vStartNew + (cone[0] - vStart);
4883:       coneNew[1] = vStartNew + (cone[1] - vStart);
4884:       DMPlexSetCone(rdm, newp, coneNew);
4885: #if defined(PETSC_USE_DEBUG)
4886:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
4887:       for (p = 0; p < 2; ++p) {
4888:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
4889:       }
4890: #endif
4891:       for (s = 0; s < size; ++s) {
4892:         DMPlexGetConeSize(dm, support[s], &fsize);
4893:         DMPlexGetCone(dm, support[s], &fcone);
4894:         for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
4895:         if ((c < 2) || (c > 3)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Edge %D not found in cone of face %D", e, support[s]);
4896:         supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + c-2;
4897:       }
4898:       DMPlexSetSupport(rdm, newp, supportRef);
4899: #if defined(PETSC_USE_DEBUG)
4900:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
4901:       for (p = 0; p < size; ++p) {
4902:         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", supportRef[p], fMaxNew, fEndNew);
4903:       }
4904: #endif
4905:     }
4906:     /* Hybrid face edges have 2 vertices and 2+2*cells faces */
4907:     for (f = fMax; f < fEnd; ++f) {
4908:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
4909:       const PetscInt *cone, *support, *ccone, *cornt;
4910:       PetscInt        coneNew[2], size, csize, s;

4912:       DMPlexGetCone(dm, f, &cone);
4913:       DMPlexGetSupportSize(dm, f, &size);
4914:       DMPlexGetSupport(dm, f, &support);
4915:       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
4916:       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
4917:       DMPlexSetCone(rdm, newp, coneNew);
4918: #if defined(PETSC_USE_DEBUG)
4919:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
4920:       for (p = 0; p < 2; ++p) {
4921:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
4922:       }
4923: #endif
4924:       supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 0;
4925:       supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 1;
4926:       for (s = 0; s < size; ++s) {
4927:         DMPlexGetConeSize(dm, support[s], &csize);
4928:         DMPlexGetCone(dm, support[s], &ccone);
4929:         DMPlexGetConeOrientation(dm, support[s], &cornt);
4930:         for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
4931:         if ((c < 2) || (c >= csize)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Hybrid face %D is not in cone of hybrid cell %D", f, support[s]);
4932:         supportRef[2+s*2+0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + c-2;
4933:         supportRef[2+s*2+1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (c-1)%3;
4934:       }
4935:       DMPlexSetSupport(rdm, newp, supportRef);
4936: #if defined(PETSC_USE_DEBUG)
4937:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
4938:       for (p = 0; p < 2+size*2; ++p) {
4939:         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", supportRef[p], fMaxNew, fEndNew);
4940:       }
4941: #endif
4942:     }
4943:     /* Interior vertices have identical supports */
4944:     for (v = vStart; v < vEnd; ++v) {
4945:       const PetscInt  newp = vStartNew + (v - vStart);
4946:       const PetscInt *support, *cone;
4947:       PetscInt        size, s;

4949:       DMPlexGetSupportSize(dm, v, &size);
4950:       DMPlexGetSupport(dm, v, &support);
4951:       for (s = 0; s < size; ++s) {
4952:         PetscInt r = 0;

4954:         DMPlexGetCone(dm, support[s], &cone);
4955:         if (cone[1] == v) r = 1;
4956:         if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
4957:         else                   supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (support[s] - eMax);
4958:       }
4959:       DMPlexSetSupport(rdm, newp, supportRef);
4960: #if defined(PETSC_USE_DEBUG)
4961:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
4962:       for (p = 0; p < size; ++p) {
4963:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior or hybrid edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
4964:       }
4965: #endif
4966:     }
4967:     /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
4968:     for (e = eStart; e < eMax; ++e) {
4969:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
4970:       const PetscInt *cone, *support;
4971:       PetscInt       *star = NULL, starSize, faceSize = 0, cellSize = 0, coneSize, size, s;

4973:       DMPlexGetSupportSize(dm, e, &size);
4974:       DMPlexGetSupport(dm, e, &support);
4975:       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
4976:       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
4977:       for (s = 0; s < size; ++s) {
4978:         PetscInt r = 0;

4980:         if (support[s] < fMax) {
4981:           DMPlexGetConeSize(dm, support[s], &coneSize);
4982:           DMPlexGetCone(dm, support[s], &cone);
4983:           for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
4984:           supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
4985:           supportRef[2+faceSize+1] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
4986:           faceSize += 2;
4987:         } else {
4988:           supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (fMax       - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (support[s] - fMax);
4989:           ++faceSize;
4990:         }
4991:       }
4992:       DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
4993:       for (s = 0; s < starSize*2; s += 2) {
4994:         const PetscInt *cone, *ornt;
4995:         PetscInt        e01, e23;

4997:         if ((star[s] >= cStart) && (star[s] < cMax)) {
4998:           /* Check edge 0-1 */
4999:           DMPlexGetCone(dm, star[s], &cone);
5000:           DMPlexGetConeOrientation(dm, star[s], &ornt);
5001:           DMPlexGetCone(dm, cone[0], &cone);
5002:           e01  = cone[GetTriEdge_Static(ornt[0], 0)];
5003:           /* Check edge 2-3 */
5004:           DMPlexGetCone(dm, star[s], &cone);
5005:           DMPlexGetConeOrientation(dm, star[s], &ornt);
5006:           DMPlexGetCone(dm, cone[2], &cone);
5007:           e23  = cone[GetTriEdge_Static(ornt[2], 1)];
5008:           if ((e01 == e) || (e23 == e)) {supportRef[2+faceSize+cellSize++] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (star[s] - cStart);}
5009:         }
5010:       }
5011:       DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
5012:       DMPlexSetSupport(rdm, newp, supportRef);
5013: #if defined(PETSC_USE_DEBUG)
5014:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
5015:       for (p = 0; p < 2+faceSize+cellSize; ++p) {
5016:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an interior or hybrid edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
5017:       }
5018: #endif
5019:     }
5020:     PetscFree(supportRef);
5021:     DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
5022:     break;
5023:   case REFINER_SIMPLEX_TO_HEX_3D:
5024:     DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
5025:     /* All cells have 6 faces */
5026:     for (c = cStart; c < cEnd; ++c) {
5027:       const PetscInt  newp = cStartNew + (c - cStart)*4;
5028:       const PetscInt *cone, *ornt;
5029:       PetscInt        coneNew[6];
5030:       PetscInt        orntNew[6];

5032:       DMPlexGetCone(dm, c, &cone);
5033:       DMPlexGetConeOrientation(dm, c, &ornt);
5034:       /* A hex */
5035:       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 0); /* B */
5036:       orntNew[0] = ornt[0] < 0 ? -1 : 1;
5037:       coneNew[1] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 3;               /* T */
5038:       orntNew[1] = -4;
5039:       coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 0); /* F */
5040:       orntNew[2] = ornt[2] < 0 ? -1 : 1;
5041:       coneNew[3] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 0;               /* K */
5042:       orntNew[3] = -1;
5043:       coneNew[4] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 2;               /* R */
5044:       orntNew[4] = 0;
5045:       coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 0); /* L */
5046:       orntNew[5] = ornt[1] < 0 ? -1 : 1;
5047:       DMPlexSetCone(rdm, newp+0, coneNew);
5048:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
5049: #if defined(PETSC_USE_DEBUG)
5050:       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
5051:       for (p = 0; p < 6; ++p) {
5052:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5053:       }
5054: #endif
5055:       /* B hex */
5056:       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 1); /* B */
5057:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
5058:       coneNew[1] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 4;               /* T */
5059:       orntNew[1] = 0;
5060:       coneNew[2] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 0;               /* F */
5061:       orntNew[2] = 0;
5062:       coneNew[3] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 1); /* K */
5063:       orntNew[3] = ornt[3] < 0 ? -2 : 0;
5064:       coneNew[4] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 1;               /* R */
5065:       orntNew[4] = 0;
5066:       coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 2); /* L */
5067:       orntNew[5] = ornt[1] < 0 ? -4 : 2;
5068:       DMPlexSetCone(rdm, newp+1, coneNew);
5069:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
5070: #if defined(PETSC_USE_DEBUG)
5071:       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
5072:       for (p = 0; p < 6; ++p) {
5073:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5074:       }
5075: #endif
5076:       /* C hex */
5077:       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 2); /* B */
5078:       orntNew[0] = ornt[0] < 0 ? -4 : 2;
5079:       coneNew[1] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 5;               /* T */
5080:       orntNew[1] = -4;
5081:       coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 1); /* F */
5082:       orntNew[2] = ornt[2] < 0 ? -2 : 0;
5083:       coneNew[3] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 1;               /* K */
5084:       orntNew[3] = -1;
5085:       coneNew[4] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 0); /* R */
5086:       orntNew[4] = ornt[3] < 0 ? -1 : 1;
5087:       coneNew[5] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 2;               /* L */
5088:       orntNew[5] = -4;
5089:       DMPlexSetCone(rdm, newp+2, coneNew);
5090:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
5091: #if defined(PETSC_USE_DEBUG)
5092:       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
5093:       for (p = 0; p < 6; ++p) {
5094:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5095:       }
5096: #endif
5097:       /* D hex */
5098:       coneNew[0] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 3;               /* B */
5099:       orntNew[0] = 0;
5100:       coneNew[1] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 2); /* T */
5101:       orntNew[1] = ornt[3] < 0 ? -1 : 1;
5102:       coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 2); /* F */
5103:       orntNew[2] = ornt[2] < 0 ? -4 : 2;
5104:       coneNew[3] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 4;               /* K */
5105:       orntNew[3] = -1;
5106:       coneNew[4] = fStartNew + (fEnd    - fStart)*3 + (c - cStart)*6 + 5;               /* R */
5107:       orntNew[4] = 0;
5108:       coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 1); /* L */
5109:       orntNew[5] = ornt[1] < 0 ? -2 : 0;
5110:       DMPlexSetCone(rdm, newp+3, coneNew);
5111:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
5112: #if defined(PETSC_USE_DEBUG)
5113:       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
5114:       for (p = 0; p < 6; ++p) {
5115:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5116:       }
5117: #endif
5118:     }
5119:     /* Split faces have 4 edges and the same cells as the parent */
5120:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
5121:     PetscMalloc1(2 + maxSupportSize*2, &supportRef);
5122:     for (f = fStart; f < fEnd; ++f) {
5123:       const PetscInt  newp = fStartNew + (f - fStart)*3;
5124:       const PetscInt *cone, *ornt, *support;
5125:       PetscInt        coneNew[4], orntNew[4], coneSize, supportSize, s;

5127:       DMPlexGetCone(dm, f, &cone);
5128:       DMPlexGetConeOrientation(dm, f, &ornt);
5129:       /* A quad */
5130:       coneNew[0] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
5131:       orntNew[0] = ornt[2];
5132:       coneNew[1] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
5133:       orntNew[1] = ornt[0];
5134:       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
5135:       orntNew[2] = 0;
5136:       coneNew[3] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
5137:       orntNew[3] = -2;
5138:       DMPlexSetCone(rdm, newp+0, coneNew);
5139:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
5140: #if defined(PETSC_USE_DEBUG)
5141:       if ((newp+0 < fStartNew) || (newp+0 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+0, fStartNew, fEndNew);
5142:       for (p = 0; p < 4; ++p) {
5143:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5144:       }
5145: #endif
5146:       /* B quad */
5147:       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
5148:       orntNew[0] = ornt[0];
5149:       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
5150:       orntNew[1] = ornt[1];
5151:       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
5152:       orntNew[2] = 0;
5153:       coneNew[3] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
5154:       orntNew[3] = -2;
5155:       DMPlexSetCone(rdm, newp+1, coneNew);
5156:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
5157: #if defined(PETSC_USE_DEBUG)
5158:       if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+1, fStartNew, fEndNew);
5159:       for (p = 0; p < 4; ++p) {
5160:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5161:       }
5162: #endif
5163:       /* C quad */
5164:       coneNew[0] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
5165:       orntNew[0] = ornt[1];
5166:       coneNew[1] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
5167:       orntNew[1] = ornt[2];
5168:       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
5169:       orntNew[2] = 0;
5170:       coneNew[3] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
5171:       orntNew[3] = -2;
5172:       DMPlexSetCone(rdm, newp+2, coneNew);
5173:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
5174: #if defined(PETSC_USE_DEBUG)
5175:       if ((newp+2 < fStartNew) || (newp+2 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+2, fStartNew, fEndNew);
5176:       for (p = 0; p < 4; ++p) {
5177:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5178:       }
5179: #endif
5180:       DMPlexGetSupportSize(dm, f, &supportSize);
5181:       DMPlexGetSupport(dm, f, &support);
5182:       for (r = 0; r < 3; ++r) {
5183:         for (s = 0; s < supportSize; ++s) {
5184:           PetscInt subf;
5185:           DMPlexGetConeSize(dm, support[s], &coneSize);
5186:           DMPlexGetCone(dm, support[s], &cone);
5187:           DMPlexGetConeOrientation(dm, support[s], &ornt);
5188:           for (c = 0; c < coneSize; ++c) {
5189:             if (cone[c] == f) break;
5190:           }
5191:           subf = GetTriSubfaceInverse_Static(ornt[c], r);
5192:           supportRef[s] = cStartNew + (support[s] - cStart)*4 + faces[c*3+subf];
5193:         }
5194:         DMPlexSetSupport(rdm, newp+r, supportRef);
5195: #if defined(PETSC_USE_DEBUG)
5196:         if ((newp+r < fStartNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+r, fStartNew, fEndNew);
5197:         for (p = 0; p < supportSize; ++p) {
5198:           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
5199:         }
5200: #endif
5201:       }
5202:     }
5203:     /* Interior faces have 4 edges and 2 cells */
5204:     for (c = cStart; c < cEnd; ++c) {
5205:       PetscInt        newp = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6;
5206:       const PetscInt *cone, *ornt;
5207:       PetscInt        coneNew[4], orntNew[4];
5208:       PetscInt        supportNew[2];

5210:       DMPlexGetCone(dm, c, &cone);
5211:       DMPlexGetConeOrientation(dm, c, &ornt);
5212:       /* Face {a, g, m, h} */
5213:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],0);
5214:       orntNew[0] = 0;
5215:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
5216:       orntNew[1] = 0;
5217:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
5218:       orntNew[2] = -2;
5219:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],2);
5220:       orntNew[3] = -2;
5221:       DMPlexSetCone(rdm, newp, coneNew);
5222:       DMPlexSetConeOrientation(rdm, newp, orntNew);
5223: #if defined(PETSC_USE_DEBUG)
5224:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5225:       for (p = 0; p < 4; ++p) {
5226:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5227:       }
5228: #endif
5229:       supportNew[0] = (c - cStart)*4 + 0;
5230:       supportNew[1] = (c - cStart)*4 + 1;
5231:       DMPlexSetSupport(rdm, newp, supportNew);
5232: #if defined(PETSC_USE_DEBUG)
5233:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5234:       for (p = 0; p < 2; ++p) {
5235:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5236:       }
5237: #endif
5238:       ++newp;
5239:       /* Face {g, b, l , m} */
5240:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],1);
5241:       orntNew[0] = -2;
5242:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],0);
5243:       orntNew[1] = 0;
5244:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
5245:       orntNew[2] = 0;
5246:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
5247:       orntNew[3] = -2;
5248:       DMPlexSetCone(rdm, newp, coneNew);
5249:       DMPlexSetConeOrientation(rdm, newp, orntNew);
5250: #if defined(PETSC_USE_DEBUG)
5251:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5252:       for (p = 0; p < 4; ++p) {
5253:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5254:       }
5255: #endif
5256:       supportNew[0] = (c - cStart)*4 + 1;
5257:       supportNew[1] = (c - cStart)*4 + 2;
5258:       DMPlexSetSupport(rdm, newp, supportNew);
5259: #if defined(PETSC_USE_DEBUG)
5260:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5261:       for (p = 0; p < 2; ++p) {
5262:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5263:       }
5264: #endif
5265:       ++newp;
5266:       /* Face {c, g, m, i} */
5267:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],2);
5268:       orntNew[0] = 0;
5269:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
5270:       orntNew[1] = 0;
5271:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
5272:       orntNew[2] = -2;
5273:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],0);
5274:       orntNew[3] = -2;
5275:       DMPlexSetCone(rdm, newp, coneNew);
5276:       DMPlexSetConeOrientation(rdm, newp, orntNew);
5277: #if defined(PETSC_USE_DEBUG)
5278:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5279:       for (p = 0; p < 4; ++p) {
5280:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5281:       }
5282: #endif
5283:       supportNew[0] = (c - cStart)*4 + 0;
5284:       supportNew[1] = (c - cStart)*4 + 2;
5285:       DMPlexSetSupport(rdm, newp, supportNew);
5286: #if defined(PETSC_USE_DEBUG)
5287:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5288:       for (p = 0; p < 2; ++p) {
5289:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5290:       }
5291: #endif
5292:       ++newp;
5293:       /* Face {d, h, m, i} */
5294:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],0);
5295:       orntNew[0] = 0;
5296:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
5297:       orntNew[1] = 0;
5298:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
5299:       orntNew[2] = -2;
5300:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],2);
5301:       orntNew[3] = -2;
5302:       DMPlexSetCone(rdm, newp, coneNew);
5303:       DMPlexSetConeOrientation(rdm, newp, orntNew);
5304: #if defined(PETSC_USE_DEBUG)
5305:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5306:       for (p = 0; p < 4; ++p) {
5307:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5308:       }
5309: #endif
5310:       supportNew[0] = (c - cStart)*4 + 0;
5311:       supportNew[1] = (c - cStart)*4 + 3;
5312:       DMPlexSetSupport(rdm, newp, supportNew);
5313: #if defined(PETSC_USE_DEBUG)
5314:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5315:       for (p = 0; p < 2; ++p) {
5316:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5317:       }
5318: #endif
5319:       ++newp;
5320:       /* Face {h, m, l, e} */
5321:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
5322:       orntNew[0] = 0;
5323:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
5324:       orntNew[1] = -2;
5325:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],1);
5326:       orntNew[2] = -2;
5327:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],1);
5328:       orntNew[3] = 0;
5329:       DMPlexSetCone(rdm, newp, coneNew);
5330:       DMPlexSetConeOrientation(rdm, newp, orntNew);
5331: #if defined(PETSC_USE_DEBUG)
5332:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5333:       for (p = 0; p < 4; ++p) {
5334:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5335:       }
5336: #endif
5337:       supportNew[0] = (c - cStart)*4 + 1;
5338:       supportNew[1] = (c - cStart)*4 + 3;
5339:       DMPlexSetSupport(rdm, newp, supportNew);
5340: #if defined(PETSC_USE_DEBUG)
5341:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5342:       for (p = 0; p < 2; ++p) {
5343:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5344:       }
5345: #endif
5346:       ++newp;
5347:       /* Face {i, m, l, f} */
5348:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
5349:       orntNew[0] = 0;
5350:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
5351:       orntNew[1] = -2;
5352:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],2);
5353:       orntNew[2] = -2;
5354:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],1);
5355:       orntNew[3] = 0;
5356:       DMPlexSetCone(rdm, newp, coneNew);
5357:       DMPlexSetConeOrientation(rdm, newp, orntNew);
5358: #if defined(PETSC_USE_DEBUG)
5359:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5360:       for (p = 0; p < 4; ++p) {
5361:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5362:       }
5363: #endif
5364:       supportNew[0] = (c - cStart)*4 + 2;
5365:       supportNew[1] = (c - cStart)*4 + 3;
5366:       DMPlexSetSupport(rdm, newp, supportNew);
5367: #if defined(PETSC_USE_DEBUG)
5368:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5369:       for (p = 0; p < 2; ++p) {
5370:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5371:       }
5372: #endif
5373:       ++newp;
5374:     }
5375:     /* Split Edges have 2 vertices and the same faces as the parent */
5376:     for (e = eStart; e < eEnd; ++e) {
5377:       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);

5379:       for (r = 0; r < 2; ++r) {
5380:         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
5381:         const PetscInt *cone, *ornt, *support;
5382:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

5384:         DMPlexGetCone(dm, e, &cone);
5385:         coneNew[0]       = vStartNew + (cone[0] - vStart);
5386:         coneNew[1]       = vStartNew + (cone[1] - vStart);
5387:         coneNew[(r+1)%2] = newv;
5388:         DMPlexSetCone(rdm, newp, coneNew);
5389: #if defined(PETSC_USE_DEBUG)
5390:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
5391:         for (p = 0; p < 2; ++p) {
5392:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
5393:         }
5394: #endif
5395:         DMPlexGetSupportSize(dm, e, &supportSize);
5396:         DMPlexGetSupport(dm, e, &support);
5397:         for (s = 0; s < supportSize; ++s) {
5398:           DMPlexGetConeSize(dm, support[s], &coneSize);
5399:           DMPlexGetCone(dm, support[s], &cone);
5400:           DMPlexGetConeOrientation(dm, support[s], &ornt);
5401:           for (c = 0; c < coneSize; ++c) {
5402:             if (cone[c] == e) break;
5403:           }
5404:           supportRef[s] = fStartNew + (support[s] - fStart)*3 + (c + (ornt[c] < 0 ? 1-r : r))%3;
5405:         }
5406:         DMPlexSetSupport(rdm, newp, supportRef);
5407: #if defined(PETSC_USE_DEBUG)
5408:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
5409:         for (p = 0; p < supportSize; ++p) {
5410:           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
5411:         }
5412: #endif
5413:       }
5414:     }
5415:     /* Face edges have 2 vertices and 2 + cell faces supports */
5416:     for (f = fStart; f < fEnd; ++f) {
5417:       const PetscInt *cone, *ornt, *support;
5418:       PetscInt        coneSize, supportSize, s;

5420:       DMPlexGetSupportSize(dm, f, &supportSize);
5421:       DMPlexGetSupport(dm, f, &support);
5422:       for (r = 0; r < 3; ++r) {
5423:         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
5424:         PetscInt        coneNew[2];
5425:         PetscInt        fint[4][3] = { {0, 1, 2},
5426:                                        {3, 4, 0},
5427:                                        {2, 5, 3},
5428:                                        {1, 4, 5} };

5430:         DMPlexGetCone(dm, f, &cone);
5431:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
5432:         coneNew[1] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + f - fStart;
5433:         DMPlexSetCone(rdm, newp, coneNew);
5434: #if defined(PETSC_USE_DEBUG)
5435:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
5436:         for (p = 0; p < 2; ++p) {
5437:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
5438:         }
5439: #endif
5440:         supportRef[0] = fStartNew + (f - fStart)*3 + (r+0)%3;
5441:         supportRef[1] = fStartNew + (f - fStart)*3 + (r+1)%3;
5442:         for (s = 0; s < supportSize; ++s) {
5443:           PetscInt er;
5444:           DMPlexGetConeSize(dm, support[s], &coneSize);
5445:           DMPlexGetCone(dm, support[s], &cone);
5446:           DMPlexGetConeOrientation(dm, support[s], &ornt);
5447:           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
5448:           er = GetTriInteriorEdgeInverse_Static(ornt[c], r);
5449:           supportRef[2+s] = fStartNew + (fEnd - fStart)*3 + (support[s] - cStart)*6 + fint[c][er];
5450:         }
5451:         DMPlexSetSupport(rdm, newp, supportRef);
5452: #if defined(PETSC_USE_DEBUG)
5453:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
5454:         for (p = 0; p < supportSize + 2; ++p) {
5455:           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
5456:         }
5457: #endif
5458:       }
5459:     }
5460:     /* Interior cell edges have 2 vertices and 3 faces */
5461:     for (c = cStart; c < cEnd; ++c) {
5462:       const PetscInt *cone;
5463:       PetscInt       fint[4][3] = { {0,1,2},
5464:                                     {0,3,4},
5465:                                     {2,3,5},
5466:                                     {1,4,5} } ;

5468:       DMPlexGetCone(dm, c, &cone);
5469:       for (r = 0; r < 4; r++) {
5470:         PetscInt       coneNew[2], supportNew[3];
5471:         const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + r;

5473:         coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
5474:         coneNew[1] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd -fStart) + c - cStart;
5475:         DMPlexSetCone(rdm, newp, coneNew);
5476: #if defined(PETSC_USE_DEBUG)
5477:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
5478:         for (p = 0; p < 2; ++p) {
5479:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
5480:         }
5481: #endif
5482:         supportNew[0] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + fint[r][0];
5483:         supportNew[1] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + fint[r][1];
5484:         supportNew[2] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + fint[r][2];
5485:         DMPlexSetSupport(rdm, newp, supportNew);
5486: #if defined(PETSC_USE_DEBUG)
5487:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
5488:         for (p = 0; p < 3; ++p) {
5489:           if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fEndNew);
5490:         }
5491: #endif
5492:       }
5493:     }
5494:     /* Old vertices have identical supports */
5495:     for (v = vStart; v < vEnd; ++v) {
5496:       const PetscInt  newp = vStartNew + (v - vStart);
5497:       const PetscInt *support, *cone;
5498:       PetscInt        size, s;

5500:       DMPlexGetSupportSize(dm, v, &size);
5501:       DMPlexGetSupport(dm, v, &support);
5502:       for (s = 0; s < size; ++s) {
5503:         PetscInt r = 0;

5505:         DMPlexGetCone(dm, support[s], &cone);
5506:         if (cone[1] == v) r = 1;
5507:         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
5508:       }
5509:       DMPlexSetSupport(rdm, newp, supportRef);
5510: #if defined(PETSC_USE_DEBUG)
5511:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
5512:       for (p = 0; p < size; ++p) {
5513:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
5514:       }
5515: #endif
5516:     }
5517:     /* Edge vertices have 2 + faces supports */
5518:     for (e = eStart; e < eEnd; ++e) {
5519:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
5520:       const PetscInt *cone, *support;
5521:       PetscInt        size, s;

5523:       DMPlexGetSupportSize(dm, e, &size);
5524:       DMPlexGetSupport(dm, e, &support);
5525:       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
5526:       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
5527:       for (s = 0; s < size; ++s) {
5528:         PetscInt r = 0, coneSize;

5530:         DMPlexGetConeSize(dm, support[s], &coneSize);
5531:         DMPlexGetCone(dm, support[s], &cone);
5532:         for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
5533:         supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + r;
5534:       }
5535:       DMPlexSetSupport(rdm, newp, supportRef);
5536: #if defined(PETSC_USE_DEBUG)
5537:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
5538:       for (p = 0; p < 2+size; ++p) {
5539:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
5540:       }
5541: #endif
5542:     }
5543:     /* Face vertices have 3 + cells supports */
5544:     for (f = fStart; f < fEnd; ++f) {
5545:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
5546:       const PetscInt *cone, *support;
5547:       PetscInt        size, s;

5549:       DMPlexGetSupportSize(dm, f, &size);
5550:       DMPlexGetSupport(dm, f, &support);
5551:       supportRef[0] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
5552:       supportRef[1] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
5553:       supportRef[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
5554:       for (s = 0; s < size; ++s) {
5555:         PetscInt r = 0, coneSize;

5557:         DMPlexGetConeSize(dm, support[s], &coneSize);
5558:         DMPlexGetCone(dm, support[s], &cone);
5559:         for (r = 0; r < coneSize; ++r) {if (cone[r] == f) break;}
5560:         supportRef[3+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (support[s] - cStart)*4 + r;
5561:       }
5562:       DMPlexSetSupport(rdm, newp, supportRef);
5563: #if defined(PETSC_USE_DEBUG)
5564:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
5565:       for (p = 0; p < 3+size; ++p) {
5566:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
5567:       }
5568: #endif
5569:     }
5570:     /* Interior cell vertices have 4 supports */
5571:     for (c = cStart; c < cEnd; ++c) {
5572:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + c - cStart;
5573:       supportRef[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
5574:       supportRef[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
5575:       supportRef[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
5576:       supportRef[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
5577:       DMPlexSetSupport(rdm, newp, supportRef);
5578: #if defined(PETSC_USE_DEBUG)
5579:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
5580:       for (p = 0; p < 4; ++p) {
5581:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
5582:       }
5583: #endif
5584:     }
5585:     PetscFree(supportRef);
5586:     DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
5587:     break;
5588:   case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
5589:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
5590:     cMax = PetscMin(cEnd, cMax);
5591:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
5592:     fMax = PetscMin(fEnd, fMax);
5593:     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
5594:     eMax = PetscMin(eEnd, eMax);
5595:     DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
5596:     /* All cells have 6 faces */
5597:     for (c = cStart; c < cMax; ++c) {
5598:       const PetscInt  newp = cStartNew + (c - cStart)*4;
5599:       const PetscInt *cone, *ornt;
5600:       PetscInt        coneNew[6];
5601:       PetscInt        orntNew[6];

5603:       DMPlexGetCone(dm, c, &cone);
5604: #if defined(PETSC_USE_DEBUG)
5605:       for (p = 0; p < 4; ++p) {
5606:         if (cone[p] >= fMax) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position %D for cell %D", cone[p], p, fMax, c);
5607:       }
5608: #endif
5609:       DMPlexGetConeOrientation(dm, c, &ornt);
5610:       /* A hex */
5611:       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 0); /* B */
5612:       orntNew[0] = ornt[0] < 0 ? -1 : 1;
5613:       coneNew[1] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 3;               /* T */
5614:       orntNew[1] = -4;
5615:       coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 0); /* F */
5616:       orntNew[2] = ornt[2] < 0 ? -1 : 1;
5617:       coneNew[3] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 0;               /* K */
5618:       orntNew[3] = -1;
5619:       coneNew[4] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 2;               /* R */
5620:       orntNew[4] = 0;
5621:       coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 0); /* L */
5622:       orntNew[5] = ornt[1] < 0 ? -1 : 1;
5623:       DMPlexSetCone(rdm, newp+0, coneNew);
5624:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
5625: #if defined(PETSC_USE_DEBUG)
5626:       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
5627:       for (p = 0; p < 6; ++p) {
5628:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5629:       }
5630: #endif
5631:       /* B hex */
5632:       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 1); /* B */
5633:       orntNew[0] = ornt[0] < 0 ? -2 : 0;
5634:       coneNew[1] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 4;               /* T */
5635:       orntNew[1] = 0;
5636:       coneNew[2] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 0;               /* F */
5637:       orntNew[2] = 0;
5638:       coneNew[3] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 1); /* K */
5639:       orntNew[3] = ornt[3] < 0 ? -2 : 0;
5640:       coneNew[4] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 1;               /* R */
5641:       orntNew[4] = 0;
5642:       coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 2); /* L */
5643:       orntNew[5] = ornt[1] < 0 ? -4 : 2;
5644:       DMPlexSetCone(rdm, newp+1, coneNew);
5645:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
5646: #if defined(PETSC_USE_DEBUG)
5647:       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
5648:       for (p = 0; p < 6; ++p) {
5649:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5650:       }
5651: #endif
5652:       /* C hex */
5653:       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 2); /* B */
5654:       orntNew[0] = ornt[0] < 0 ? -4 : 2;
5655:       coneNew[1] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 5;               /* T */
5656:       orntNew[1] = -4;
5657:       coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 1); /* F */
5658:       orntNew[2] = ornt[2] < 0 ? -2 : 0;
5659:       coneNew[3] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 1;               /* K */
5660:       orntNew[3] = -1;
5661:       coneNew[4] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 0); /* R */
5662:       orntNew[4] = ornt[3] < 0 ? -1 : 1;
5663:       coneNew[5] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 2;               /* L */
5664:       orntNew[5] = -4;
5665:       DMPlexSetCone(rdm, newp+2, coneNew);
5666:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
5667: #if defined(PETSC_USE_DEBUG)
5668:       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
5669:       for (p = 0; p < 6; ++p) {
5670:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5671:       }
5672: #endif
5673:       /* D hex */
5674:       coneNew[0] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 3;               /* B */
5675:       orntNew[0] = 0;
5676:       coneNew[1] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 2); /* T */
5677:       orntNew[1] = ornt[3] < 0 ? -1 : 1;
5678:       coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 2); /* F */
5679:       orntNew[2] = ornt[2] < 0 ? -4 : 2;
5680:       coneNew[3] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 4;               /* K */
5681:       orntNew[3] = -1;
5682:       coneNew[4] = fStartNew + (fMax    - fStart)*3 + (c - cStart)*6 + 5;               /* R */
5683:       orntNew[4] = 0;
5684:       coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 1); /* L */
5685:       orntNew[5] = ornt[1] < 0 ? -2 : 0;
5686:       DMPlexSetCone(rdm, newp+3, coneNew);
5687:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
5688: #if defined(PETSC_USE_DEBUG)
5689:       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
5690:       for (p = 0; p < 6; ++p) {
5691:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5692:       }
5693: #endif
5694:     }
5695:     for (c = cMax; c < cEnd; ++c) {
5696:       const PetscInt  newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*3;
5697:       const PetscInt *cone, *ornt;
5698:       PetscInt        coneNew[6], orntNew[6];
5699:       PetscInt        o, of, cf;

5701:       DMPlexGetCone(dm, c, &cone);
5702: #if defined(PETSC_USE_DEBUG)
5703:       if (cone[0] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position 0 for cell %D", cone[0], fMax, c);
5704:       if (cone[1] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position 1 for cell %D", cone[1], fMax, c);
5705:       if (cone[2] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected face %D (fMax %D) in cone position 2 for cell %D", cone[2], fMax, c);
5706:       if (cone[3] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected face %D (fMax %D) in cone position 3 for cell %D", cone[3], fMax, c);
5707:       if (cone[4] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected face %D (fMax %D) in cone position 4 for cell %D", cone[4], fMax, c);
5708: #endif
5709:       DMPlexGetConeOrientation(dm, c, &ornt);
5710:       o    = ornt[0] < 0 ? -1 : 1;
5711:       o    = 1;
5712:       /* A hex */
5713:       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 0);                            /* B */
5714:       orntNew[0] = ornt[0] < 0 ? -1 :  1;
5715:       coneNew[1] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 0);                            /* T */
5716:       orntNew[1] = ornt[1] < 0 ?  1 : -1;
5717:       cf         = 2;
5718:       of         = ornt[2+cf] < 0 ? -1 : 1;
5719:       coneNew[2] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (cone[2+cf] - fMax)*2 + (o*of < 0 ? 0 : 1); /* F */
5720:       orntNew[2] = o*of < 0 ? 0 : -1;
5721:       coneNew[3] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;         /* K */
5722:       orntNew[3] = -1;
5723:       coneNew[4] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;         /* R */
5724:       orntNew[4] = 0;
5725:       cf         = 0;
5726:       of         = ornt[2+cf] < 0 ? -1 : 1;
5727:       coneNew[5] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (cone[2+cf] - fMax)*2 + (o*of < 0 ? 1 : 0); /* L */
5728:       orntNew[5] = o*of < 0 ? 1 : -4;
5729:       DMPlexSetCone(rdm, newp+0, coneNew);
5730:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
5731: #if defined(PETSC_USE_DEBUG)
5732:       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
5733:       for (p = 0; p < 6; ++p) {
5734:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5735:       }
5736: #endif
5737:       /* B hex */
5738:       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 1);                            /* B */
5739:       orntNew[0] = ornt[0] < 0 ? -2 :  0;
5740:       coneNew[1] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 1);                            /* T */
5741:       orntNew[1] = ornt[1] < 0 ?  2 : -4;
5742:       coneNew[2] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;         /* F */
5743:       orntNew[2] = 0;
5744:       cf         = 1;
5745:       of         = ornt[2+cf] < 0 ? -1 : 1;
5746:       coneNew[3] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (cone[2+cf] - fMax)*2 + (o*of < 0 ? 1 : 0); /* K */
5747:       orntNew[3] = o*of < 0 ? 0 : -1;
5748:       coneNew[4] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;         /* R */
5749:       orntNew[4] = -1;
5750:       cf         = 0;
5751:       of         = ornt[2+cf] < 0 ? -1 : 1;
5752:       coneNew[5] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (cone[2+cf] - fMax)*2 + (o*of < 0 ? 0 : 1); /* L */
5753:       orntNew[5] = o*of < 0 ? 1 : -4;
5754:       DMPlexSetCone(rdm, newp+1, coneNew);
5755:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
5756: #if defined(PETSC_USE_DEBUG)
5757:       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
5758:       for (p = 0; p < 6; ++p) {
5759:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5760:       }
5761: #endif
5762:       /* C hex */
5763:       coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 2);                            /* B */
5764:       orntNew[0] = ornt[0] < 0 ? -4 : 2;
5765:       coneNew[1] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 2);                            /* T */
5766:       orntNew[1] = ornt[1] < 0 ? 0 : -2;
5767:       cf         = 2;
5768:       of         = ornt[2+cf] < 0 ? -1 : 1;
5769:       coneNew[2] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (cone[2+cf] - fMax)*2 + (o*of < 0 ? 1 : 0); /* F */
5770:       orntNew[2] = o*of < 0 ? 0 : -1;
5771:       coneNew[3] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;         /* K */
5772:       orntNew[3] = 0;
5773:       cf         = 1;
5774:       of         = ornt[2+cf] < 0 ? -1 : 1;
5775:       coneNew[4] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (cone[2+cf] - fMax)*2 + (o*of < 0 ? 0 : 1); /* R */
5776:       orntNew[4] = o*of < 0 ? 0 : -1;
5777:       coneNew[5] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;         /* L */
5778:       orntNew[5] = -4;
5779:       DMPlexSetCone(rdm, newp+2, coneNew);
5780:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
5781: #if defined(PETSC_USE_DEBUG)
5782:       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
5783:       for (p = 0; p < 6; ++p) {
5784:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
5785:       }
5786: #endif
5787:     }

5789:     /* Split faces have 4 edges and the same cells as the parent */
5790:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
5791:     PetscMalloc1(2 + maxSupportSize*2, &supportRef);
5792:     for (f = fStart; f < fMax; ++f) {
5793:       const PetscInt  newp = fStartNew + (f - fStart)*3;
5794:       const PetscInt *cone, *ornt, *support;
5795:       PetscInt        coneNew[4], orntNew[4], coneSize, supportSize, s;

5797:       DMPlexGetCone(dm, f, &cone);
5798: #if defined(PETSC_USE_DEBUG)
5799:       for (p = 0; p < 3; ++p) {
5800:         if (cone[p] >= eMax) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid edge %D (eMax %D) in cone position %D for face %D", cone[p], p, eMax, f);
5801:       }
5802: #endif
5803:       DMPlexGetConeOrientation(dm, f, &ornt);
5804:       /* A quad */
5805:       coneNew[0] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
5806:       orntNew[0] = ornt[2];
5807:       coneNew[1] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
5808:       orntNew[1] = ornt[0];
5809:       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
5810:       orntNew[2] = 0;
5811:       coneNew[3] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
5812:       orntNew[3] = -2;
5813:       DMPlexSetCone(rdm, newp+0, coneNew);
5814:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
5815: #if defined(PETSC_USE_DEBUG)
5816:       if ((newp+0 < fStartNew) || (newp+0 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+0, fStartNew, fEndNew);
5817:       for (p = 0; p < 4; ++p) {
5818:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5819:       }
5820: #endif
5821:       /* B quad */
5822:       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
5823:       orntNew[0] = ornt[0];
5824:       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
5825:       orntNew[1] = ornt[1];
5826:       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
5827:       orntNew[2] = 0;
5828:       coneNew[3] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 0;
5829:       orntNew[3] = -2;
5830:       DMPlexSetCone(rdm, newp+1, coneNew);
5831:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
5832: #if defined(PETSC_USE_DEBUG)
5833:       if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+1, fStartNew, fEndNew);
5834:       for (p = 0; p < 4; ++p) {
5835:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5836:       }
5837: #endif
5838:       /* C quad */
5839:       coneNew[0] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
5840:       orntNew[0] = ornt[1];
5841:       coneNew[1] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
5842:       orntNew[1] = ornt[2];
5843:       coneNew[2] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 2;
5844:       orntNew[2] = 0;
5845:       coneNew[3] = eStartNew + (eMax    - eStart)*2 + (f - fStart)*3 + 1;
5846:       orntNew[3] = -2;
5847:       DMPlexSetCone(rdm, newp+2, coneNew);
5848:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
5849: #if defined(PETSC_USE_DEBUG)
5850:       if ((newp+2 < fStartNew) || (newp+2 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+2, fStartNew, fEndNew);
5851:       for (p = 0; p < 4; ++p) {
5852:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5853:       }
5854: #endif
5855:       DMPlexGetSupportSize(dm, f, &supportSize);
5856:       DMPlexGetSupport(dm, f, &support);
5857:       for (r = 0; r < 3; ++r) {
5858:         for (s = 0; s < supportSize; ++s) {
5859:           PetscInt subf;

5861:           DMPlexGetConeSize(dm, support[s], &coneSize);
5862:           if (coneSize != 5 && support[s] >= cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
5863:           if (coneSize != 4 && support[s] <  cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
5864:           DMPlexGetCone(dm, support[s], &cone);
5865:           DMPlexGetConeOrientation(dm, support[s], &ornt);
5866:           for (c = 0; c < coneSize; ++c) {
5867:             if (cone[c] == f) break;
5868:           }
5869:           subf = GetTriSubfaceInverse_Static(ornt[c], r);
5870:           if (coneSize == 4) {
5871:             supportRef[s] = cStartNew + (support[s] - cStart)*4 + faces[c*3+subf];
5872:           } else if (coneSize == 5) {
5873:             if (c != 0 && c != 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position %D in cone %D of cell %D (cMax %D) for face %D", c, support[s], cMax, f);
5874:             supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*3 + subf;
5875:           } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
5876:         }
5877:         DMPlexSetSupport(rdm, newp+r, supportRef);
5878: #if defined(PETSC_USE_DEBUG)
5879:         if ((newp+r < fStartNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+r, fStartNew, fEndNew);
5880:         for (p = 0; p < supportSize; ++p) {
5881:           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
5882:         }
5883: #endif
5884:       }
5885:     }
5886:     /* Interior faces have 4 edges and 2 cells */
5887:     for (c = cStart; c < cMax; ++c) {
5888:       PetscInt        newp = fStartNew + (fMax - fStart)*3 + (c - cStart)*6;
5889:       const PetscInt *cone, *ornt;
5890:       PetscInt        coneNew[4], orntNew[4];
5891:       PetscInt        supportNew[2];

5893:       DMPlexGetCone(dm, c, &cone);
5894: #if defined(PETSC_USE_DEBUG)
5895:       for (p = 0; p < 4; ++p) {
5896:         if (cone[p] >= fMax) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position %D for face %D", cone[p], p, fMax, f);
5897:       }
5898: #endif
5899:       DMPlexGetConeOrientation(dm, c, &ornt);
5900:       /* Face {a, g, m, h} */
5901:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],0);
5902:       orntNew[0] = 0;
5903:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 0;
5904:       orntNew[1] = 0;
5905:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 1;
5906:       orntNew[2] = -2;
5907:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],2);
5908:       orntNew[3] = -2;
5909:       DMPlexSetCone(rdm, newp, coneNew);
5910:       DMPlexSetConeOrientation(rdm, newp, orntNew);
5911: #if defined(PETSC_USE_DEBUG)
5912:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5913:       for (p = 0; p < 4; ++p) {
5914:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5915:       }
5916: #endif
5917:       supportNew[0] = cStartNew + (c - cStart)*4 + 0;
5918:       supportNew[1] = cStartNew + (c - cStart)*4 + 1;
5919:       DMPlexSetSupport(rdm, newp, supportNew);
5920: #if defined(PETSC_USE_DEBUG)
5921:       for (p = 0; p < 2; ++p) {
5922:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5923:       }
5924: #endif
5925:       ++newp;
5926:       /* Face {g, b, l , m} */
5927:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],1);
5928:       orntNew[0] = -2;
5929:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],0);
5930:       orntNew[1] = 0;
5931:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 3;
5932:       orntNew[2] = 0;
5933:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 0;
5934:       orntNew[3] = -2;
5935:       DMPlexSetCone(rdm, newp, coneNew);
5936:       DMPlexSetConeOrientation(rdm, newp, orntNew);
5937: #if defined(PETSC_USE_DEBUG)
5938:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5939:       for (p = 0; p < 4; ++p) {
5940:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5941:       }
5942: #endif
5943:       supportNew[0] = cStartNew + (c - cStart)*4 + 1;
5944:       supportNew[1] = cStartNew + (c - cStart)*4 + 2;
5945:       DMPlexSetSupport(rdm, newp, supportNew);
5946: #if defined(PETSC_USE_DEBUG)
5947:       for (p = 0; p < 2; ++p) {
5948:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5949:       }
5950: #endif
5951:       ++newp;
5952:       /* Face {c, g, m, i} */
5953:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],2);
5954:       orntNew[0] = 0;
5955:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 0;
5956:       orntNew[1] = 0;
5957:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 2;
5958:       orntNew[2] = -2;
5959:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],0);
5960:       orntNew[3] = -2;
5961:       DMPlexSetCone(rdm, newp, coneNew);
5962:       DMPlexSetConeOrientation(rdm, newp, orntNew);
5963: #if defined(PETSC_USE_DEBUG)
5964:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5965:       for (p = 0; p < 4; ++p) {
5966:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5967:       }
5968: #endif
5969:       supportNew[0] = cStartNew + (c - cStart)*4 + 0;
5970:       supportNew[1] = cStartNew + (c - cStart)*4 + 2;
5971:       DMPlexSetSupport(rdm, newp, supportNew);
5972: #if defined(PETSC_USE_DEBUG)
5973:       for (p = 0; p < 2; ++p) {
5974:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
5975:       }
5976: #endif
5977:       ++newp;
5978:       /* Face {d, h, m, i} */
5979:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],0);
5980:       orntNew[0] = 0;
5981:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 1;
5982:       orntNew[1] = 0;
5983:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 2;
5984:       orntNew[2] = -2;
5985:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],2);
5986:       orntNew[3] = -2;
5987:       DMPlexSetCone(rdm, newp, coneNew);
5988:       DMPlexSetConeOrientation(rdm, newp, orntNew);
5989: #if defined(PETSC_USE_DEBUG)
5990:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
5991:       for (p = 0; p < 4; ++p) {
5992:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
5993:       }
5994: #endif
5995:       supportNew[0] = cStartNew + (c - cStart)*4 + 0;
5996:       supportNew[1] = cStartNew + (c - cStart)*4 + 3;
5997:       DMPlexSetSupport(rdm, newp, supportNew);
5998: #if defined(PETSC_USE_DEBUG)
5999:       for (p = 0; p < 2; ++p) {
6000:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
6001:       }
6002: #endif
6003:       ++newp;
6004:       /* Face {h, m, l, e} */
6005:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 1;
6006:       orntNew[0] = 0;
6007:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 3;
6008:       orntNew[1] = -2;
6009:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],1);
6010:       orntNew[2] = -2;
6011:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],1);
6012:       orntNew[3] = 0;
6013:       DMPlexSetCone(rdm, newp, coneNew);
6014:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6015: #if defined(PETSC_USE_DEBUG)
6016:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6017:       for (p = 0; p < 4; ++p) {
6018:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6019:       }
6020: #endif
6021:       supportNew[0] = cStartNew + (c - cStart)*4 + 1;
6022:       supportNew[1] = cStartNew + (c - cStart)*4 + 3;
6023:       DMPlexSetSupport(rdm, newp, supportNew);
6024: #if defined(PETSC_USE_DEBUG)
6025:       for (p = 0; p < 2; ++p) {
6026:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
6027:       }
6028: #endif
6029:       ++newp;
6030:       /* Face {i, m, l, f} */
6031:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 2;
6032:       orntNew[0] = 0;
6033:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 3;
6034:       orntNew[1] = -2;
6035:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],2);
6036:       orntNew[2] = -2;
6037:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],1);
6038:       orntNew[3] = 0;
6039:       DMPlexSetCone(rdm, newp, coneNew);
6040:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6041: #if defined(PETSC_USE_DEBUG)
6042:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6043:       for (p = 0; p < 4; ++p) {
6044:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6045:       }
6046: #endif
6047:       supportNew[0] = cStartNew + (c - cStart)*4 + 2;
6048:       supportNew[1] = cStartNew + (c - cStart)*4 + 3;
6049:       DMPlexSetSupport(rdm, newp, supportNew);
6050: #if defined(PETSC_USE_DEBUG)
6051:       for (p = 0; p < 2; ++p) {
6052:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
6053:       }
6054: #endif
6055:       ++newp;
6056:     }
6057:     /* Hybrid split faces have 4 edges and same cells */
6058:     for (f = fMax; f < fEnd; ++f) {
6059:       const PetscInt *cone, *ornt, *support;
6060:       PetscInt        coneNew[4], orntNew[4];
6061:       PetscInt        size, s;
6062:       const PetscInt  newp = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (f - fMax)*2;

6064:       DMPlexGetCone(dm, f, &cone);
6065: #if defined(PETSC_USE_DEBUG)
6066:       if (cone[0] >= eMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid edge %D (eMax %D) in cone position 0 for face %D", cone[0], eMax, f);
6067:       if (cone[1] >= eMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid edge %D (eMax %D) in cone position 1 for face %D", cone[1], eMax, f);
6068:       if (cone[2] <  eMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected edge %D (eMax %D) in cone position 2 for face %D", cone[2], eMax, f);
6069:       if (cone[3] <  eMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected edge %D (eMax %D) in cone position 3 for face %D", cone[3], eMax, f);
6070: #endif
6071:       DMPlexGetConeOrientation(dm, f, &ornt);
6072:       /* A face */
6073:       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
6074:       orntNew[0] = ornt[0];
6075:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (f - fMax);
6076:       orntNew[1] = 0;
6077:       coneNew[2] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
6078:       orntNew[2] = ornt[1] < 0 ? 0 : -2;
6079:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (cone[2] - eMax);
6080:       orntNew[3] = ornt[2] < 0 ? 0 : -2;
6081:       DMPlexSetCone(rdm, newp, coneNew);
6082:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6083: #if defined(PETSC_USE_DEBUG)
6084:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6085:       for (p = 0; p < 4; ++p) {
6086:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6087:       }
6088: #endif

6090:       /* B face */
6091:       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
6092:       orntNew[0] = ornt[0];
6093:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (cone[3] - eMax);
6094:       orntNew[1] = ornt[3];
6095:       coneNew[2] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
6096:       orntNew[2] = ornt[1] < 0 ? 0 : -2;
6097:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (f - fMax);
6098:       orntNew[3] = -2;
6099:       DMPlexSetCone(rdm, newp+1, coneNew);
6100:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
6101: #if defined(PETSC_USE_DEBUG)
6102:       if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp+1, fStartNew, fEndNew);
6103:       for (p = 0; p < 4; ++p) {
6104:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6105:       }
6106: #endif

6108:       DMPlexGetSupportSize(dm, f, &size);
6109:       DMPlexGetSupport(dm, f, &support);
6110:       for (r = 0; r < 2; ++r) {
6111:         for (s = 0; s < size; ++s) {
6112:           const PetscInt *coneCell, *orntCell;
6113:           PetscInt        coneSize, o, of, c;

6115:           DMPlexGetConeSize(dm, support[s], &coneSize);
6116:           if (coneSize != 5 || support[s] < cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
6117:           DMPlexGetCone(dm, support[s], &coneCell);
6118:           DMPlexGetConeOrientation(dm, support[s], &orntCell);
6119:           o = orntCell[0] < 0 ? -1 : 1;
6120:           o = 1;
6121:           for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
6122:           if (c == 0 || c == 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position in cone %D of cell %D (cMax %D) for face %D", c, support[s], cMax, f);
6123:           if (c == coneSize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %D in cone of cell %D", f, support[s]);
6124:           of = orntCell[c] < 0 ? -1 : 1;
6125:           supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*3 + (c-2 + (o*of < 0 ? 1-r : r))%3;
6126:         }
6127:         DMPlexSetSupport(rdm, newp + r, supportRef);
6128: #if defined(PETSC_USE_DEBUG)
6129:         for (p = 0; p < size; ++p) {
6130:           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
6131:         }
6132: #endif
6133:       }
6134:     }
6135:     /* Interior hybrid faces have 4 edges and 2 cells */
6136:     for (c = cMax; c < cEnd; ++c) {
6137:       PetscInt        newp = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3;
6138:       const PetscInt *cone, *ornt;
6139:       PetscInt        coneNew[4], orntNew[4];
6140:       PetscInt        supportNew[2];

6142:       DMPlexGetCone(dm, c, &cone);
6143: #if defined(PETSC_USE_DEBUG)
6144:       if (cone[0] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position 0 for cell %D", cone[0], fMax, c);
6145:       if (cone[1] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position 1 for cell %D", cone[1], fMax, c);
6146:       if (cone[2] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected face %D (fMax %D) in cone position 2 for cell %D", cone[2], fMax, c);
6147:       if (cone[3] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected face %D (fMax %D) in cone position 3 for cell %D", cone[3], fMax, c);
6148:       if (cone[4] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected face %D (fMax %D) in cone position 3 for cell %D", cone[3], fMax, c);
6149: #endif
6150:       DMPlexGetConeOrientation(dm, c, &ornt);
6151:       /* Face {a, g, h, d} */
6152:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],0);
6153:       orntNew[0] = 0;
6154:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + c - cMax;
6155:       orntNew[1] = 0;
6156:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],0);
6157:       orntNew[2] = -2;
6158:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (cone[2] - fMax);
6159:       orntNew[3] = -2;
6160:       DMPlexSetCone(rdm, newp, coneNew);
6161:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6162: #if defined(PETSC_USE_DEBUG)
6163:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6164:       for (p = 0; p < 4; ++p) {
6165:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6166:       }
6167: #endif
6168:       supportNew[0] = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + 0;
6169:       supportNew[1] = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + 1;
6170:       DMPlexSetSupport(rdm, newp, supportNew);
6171: #if defined(PETSC_USE_DEBUG)
6172:       for (p = 0; p < 2; ++p) {
6173:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
6174:       }
6175: #endif
6176:       ++newp;
6177:       /* Face {b, g, h, l} */
6178:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],1);
6179:       orntNew[0] = 0;
6180:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + c - cMax;
6181:       orntNew[1] = 0;
6182:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],1);
6183:       orntNew[2] = -2;
6184:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (cone[3] - fMax);
6185:       orntNew[3] = -2;
6186:       DMPlexSetCone(rdm, newp, coneNew);
6187:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6188: #if defined(PETSC_USE_DEBUG)
6189:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6190:       for (p = 0; p < 4; ++p) {
6191:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6192:       }
6193: #endif
6194:       supportNew[0] = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + 1;
6195:       supportNew[1] = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + 2;
6196:       DMPlexSetSupport(rdm, newp, supportNew);
6197: #if defined(PETSC_USE_DEBUG)
6198:       for (p = 0; p < 2; ++p) {
6199:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
6200:       }
6201: #endif
6202:       ++newp;
6203:       /* Face {c, g, h, f} */
6204:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],2);
6205:       orntNew[0] = 0;
6206:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + c - cMax;
6207:       orntNew[1] = 0;
6208:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],2);
6209:       orntNew[2] = -2;
6210:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (cone[4] - fMax);
6211:       orntNew[3] = -2;
6212:       DMPlexSetCone(rdm, newp, coneNew);
6213:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6214: #if defined(PETSC_USE_DEBUG)
6215:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6216:       for (p = 0; p < 4; ++p) {
6217:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6218:       }
6219: #endif
6220:       supportNew[0] = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + 2;
6221:       supportNew[1] = cStartNew + (cMax - cStart)*4 + (c - cMax)*3 + 0;
6222:       DMPlexSetSupport(rdm, newp, supportNew);
6223: #if defined(PETSC_USE_DEBUG)
6224:       for (p = 0; p < 2; ++p) {
6225:         if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
6226:       }
6227: #endif
6228:     }
6229:     /* Face edges have 2 vertices and 2 + cell faces supports */
6230:     for (f = fStart; f < fMax; ++f) {
6231:       const PetscInt *cone, *ornt, *support;
6232:       PetscInt        coneSize, supportSize, s;

6234:       DMPlexGetSupportSize(dm, f, &supportSize);
6235:       DMPlexGetSupport(dm, f, &support);
6236:       for (r = 0; r < 3; ++r) {
6237:         const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
6238:         PetscInt        coneNew[2];
6239:         PetscInt        fint[4][3] = { {0, 1, 2},
6240:                                        {3, 4, 0},
6241:                                        {2, 5, 3},
6242:                                        {1, 4, 5} };

6244:         DMPlexGetCone(dm, f, &cone);
6245:         if (cone[r] >= eMax) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected cone point %D in position %D for face %D (eMax %D)", cone[r], r, f, eMax);
6246:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
6247:         coneNew[1] = vStartNew + (vEnd - vStart) + (eMax - eStart) + f - fStart;
6248:         DMPlexSetCone(rdm, newp, coneNew);
6249: #if defined(PETSC_USE_DEBUG)
6250:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6251:         for (p = 0; p < 2; ++p) {
6252:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
6253:         }
6254: #endif
6255:         supportRef[0] = fStartNew + (f - fStart)*3 + (r+0)%3;
6256:         supportRef[1] = fStartNew + (f - fStart)*3 + (r+1)%3;
6257:         for (s = 0; s < supportSize; ++s) {
6258:           PetscInt er;

6260:           supportRef[2+s] = -1;
6261:           DMPlexGetConeSize(dm, support[s], &coneSize);
6262:           if (coneSize != 5 && support[s] >= cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
6263:           if (coneSize != 4 && support[s] <  cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
6264:           DMPlexGetCone(dm, support[s], &cone);
6265:           DMPlexGetConeOrientation(dm, support[s], &ornt);
6266:           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
6267:           er = GetTriInteriorEdgeInverse_Static(ornt[c], r);
6268:           if (coneSize == 4) {
6269:             supportRef[2+s] = fStartNew + (fMax - fStart)*3 + (support[s] - cStart)*6 + fint[c][er];
6270:           } else if (coneSize == 5) {
6271:             if (c != 0 && c != 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position %D in cone %D of cell %D (cMax %D) for face %D", c, support[s], cMax, f);
6272:             supportRef[2+s] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + er;
6273:           }
6274:         }
6275:         DMPlexSetSupport(rdm, newp, supportRef);
6276: #if defined(PETSC_USE_DEBUG)
6277:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6278:         for (p = 0; p < supportSize + 2; ++p) {
6279:           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
6280:         }
6281: #endif
6282:       }
6283:     }
6284:     /* Interior cell edges have 2 vertices and 3 faces */
6285:     for (c = cStart; c < cMax; ++c) {
6286:       const PetscInt *cone;
6287:       PetscInt       fint[4][3] = { {0,1,2},
6288:                                     {0,3,4},
6289:                                     {2,3,5},
6290:                                     {1,4,5} } ;

6292:       DMPlexGetCone(dm, c, &cone);
6293:       for (r = 0; r < 4; r++) {
6294:         PetscInt       coneNew[2], supportNew[3];
6295:         const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + r;

6297:         if (cone[r] >= fMax) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position %D for cell %D", cone[r], r, fMax, c);
6298:         coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[r] - fStart);
6299:         coneNew[1] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax     -fStart) + c - cStart;
6300:         DMPlexSetCone(rdm, newp, coneNew);
6301: #if defined(PETSC_USE_DEBUG)
6302:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6303:         for (p = 0; p < 2; ++p) {
6304:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
6305:         }
6306: #endif
6307:         supportNew[0] = fStartNew + (fMax - fStart)*3 + (c - cStart)*6 + fint[r][0];
6308:         supportNew[1] = fStartNew + (fMax - fStart)*3 + (c - cStart)*6 + fint[r][1];
6309:         supportNew[2] = fStartNew + (fMax - fStart)*3 + (c - cStart)*6 + fint[r][2];
6310:         DMPlexSetSupport(rdm, newp, supportNew);
6311: #if defined(PETSC_USE_DEBUG)
6312:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6313:         for (p = 0; p < 3; ++p) {
6314:           if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fEndNew);
6315:         }
6316: #endif
6317:       }
6318:     }
6319:     /* Hybrid edges have two vertices and the same faces */
6320:     for (e = eMax; e < eEnd; ++e) {
6321:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (e - eMax);
6322:       const PetscInt *cone, *support, *fcone;
6323:       PetscInt        coneNew[2], size, fsize, s;

6325:       DMPlexGetCone(dm, e, &cone);
6326:       DMPlexGetSupportSize(dm, e, &size);
6327:       DMPlexGetSupport(dm, e, &support);
6328:       coneNew[0] = vStartNew + (cone[0] - vStart);
6329:       coneNew[1] = vStartNew + (cone[1] - vStart);
6330:       DMPlexSetCone(rdm, newp, coneNew);
6331: #if defined(PETSC_USE_DEBUG)
6332:       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is a edge [%D, %D)", newp, eStartNew, eEndNew);
6333:       for (p = 0; p < 2; ++p) {
6334:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
6335:       }
6336: #endif
6337:       for (s = 0; s < size; ++s) {
6338:         DMPlexGetConeSize(dm, support[s], &fsize);
6339:         DMPlexGetCone(dm, support[s], &fcone);
6340:         for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
6341:         if ((c < 2) || (c > 3)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Edge %D not found in cone of face %D", e, support[s]);
6342:         supportRef[s] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (support[s] - fMax)*2 + c-2;
6343:       }
6344:       DMPlexSetSupport(rdm, newp, supportRef);
6345: #if defined(PETSC_USE_DEBUG)
6346:       for (p = 0; p < size; ++p) {
6347:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
6348:       }
6349: #endif
6350:     }
6351:     /* Hybrid face edges have 2 vertices and 2 + cell faces supports */
6352:     for (f = fMax; f < fEnd; ++f) {
6353:       const PetscInt *cone, *ornt, *support;
6354:       PetscInt        coneSize, supportSize;
6355:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + f - fMax;
6356:       PetscInt        coneNew[2], s;

6358:       DMPlexGetCone(dm, f, &cone);
6359: #if defined(PETSC_USE_DEBUG)
6360:       if (cone[0] >= eMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected cone point %D in position 0 for face %D (eMax %D)", cone[0], f, eMax);
6361:       if (cone[1] >= eMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected cone point %D in position 1 for face %D (eMax %D)", cone[1], f, eMax);
6362: #endif
6363:       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
6364:       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
6365:       DMPlexSetCone(rdm, newp, coneNew);
6366: #if defined(PETSC_USE_DEBUG)
6367:       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6368:       for (p = 0; p < 2; ++p) {
6369:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
6370:       }
6371: #endif
6372:       supportRef[0] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (f- fMax)*2 + 0;
6373:       supportRef[1] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (f- fMax)*2 + 1;
6374:       DMPlexGetSupportSize(dm, f, &supportSize);
6375:       DMPlexGetSupport(dm, f, &support);
6376:       for (s = 0; s < supportSize; ++s) {
6377:         DMPlexGetConeSize(dm, support[s], &coneSize);
6378:         if (coneSize != 5 || support[s] < cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
6379:         DMPlexGetCone(dm, support[s], &cone);
6380:         DMPlexGetConeOrientation(dm, support[s], &ornt);
6381:         for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
6382:         if (c == 0 || c == 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position in cone %D of cell %D (cMax %D) for face %D", c, support[s], cMax, f);
6383:         supportRef[2+s] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + c - 2;
6384:       }
6385:       DMPlexSetSupport(rdm, newp, supportRef);
6386: #if defined(PETSC_USE_DEBUG)
6387:       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6388:       for (p = 0; p < supportSize + 2; ++p) {
6389:         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
6390:       }
6391: #endif
6392:     }
6393:     /* Hybrid cell edges have 2 vertices and 3 faces */
6394:     for (c = cMax; c < cEnd; ++c) {
6395:       PetscInt       coneNew[2], supportNew[3];
6396:       const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + c - cMax;
6397:       const PetscInt *cone;

6399:       DMPlexGetCone(dm, c, &cone);
6400: #if defined(PETSC_USE_DEBUG)
6401:       if (cone[0] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position 0 for cell %D", cone[0], fMax, c);
6402:       if (cone[1] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected hybrid face %D (fMax %D) in cone position 1 for cell %D", cone[1], fMax, c);
6403: #endif
6404:       coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[0] - fStart);
6405:       coneNew[1] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[1] - fStart);
6406:       DMPlexSetCone(rdm, newp, coneNew);
6407: #if defined(PETSC_USE_DEBUG)
6408:       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6409:       for (p = 0; p < 2; ++p) {
6410:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
6411:       }
6412: #endif
6413:       supportNew[0] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;
6414:       supportNew[1] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;
6415:       supportNew[2] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;
6416:       DMPlexSetSupport(rdm, newp, supportNew);
6417: #if defined(PETSC_USE_DEBUG)
6418:       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6419:       for (p = 0; p < 3; ++p) {
6420:         if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fEndNew);
6421:       }
6422: #endif
6423:     }
6424:     /* Old vertices have identical supports */
6425:     for (v = vStart; v < vEnd; ++v) {
6426:       const PetscInt  newp = vStartNew + (v - vStart);
6427:       const PetscInt *support, *cone;
6428:       PetscInt        size, s;

6430:       DMPlexGetSupportSize(dm, v, &size);
6431:       DMPlexGetSupport(dm, v, &support);
6432:       for (s = 0; s < size; ++s) {
6433:         const PetscInt e = support[s];

6435:         supportRef[s] = -1;
6436:         if (eStart <= e) {
6437:           if (e < eMax) {
6438:             DMPlexGetCone(dm, e, &cone);
6439:             supportRef[s] = eStartNew + (e - eStart)*2 + (cone[1] == v ? 1 : 0);
6440:           } else if (e < eEnd) {
6441:             supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + e - eMax;
6442:           } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", e, eStart, eEnd);
6443:         } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", e, eStart, eEnd);
6444:       }
6445:       DMPlexSetSupport(rdm, newp, supportRef);
6446: #if defined(PETSC_USE_DEBUG)
6447:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
6448:       for (p = 0; p < size; ++p) {
6449:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
6450:       }
6451: #endif
6452:     }
6453:     /* Interior edge vertices have 2 + faces supports */
6454:     for (e = eStart; e < eMax; ++e) {
6455:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
6456:       const PetscInt *cone, *support;
6457:       PetscInt        size, s;

6459:       DMPlexGetSupportSize(dm, e, &size);
6460:       DMPlexGetSupport(dm, e, &support);
6461:       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
6462:       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
6463:       for (s = 0; s < size; ++s) {
6464:         PetscInt r, coneSize;

6466:         supportRef[2+s] = -1;
6467:         DMPlexGetConeSize(dm, support[s], &coneSize);
6468:         if (coneSize != 4 && support[s] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for face %D (fMax %D)", coneSize, support[s], fMax);
6469:         if (coneSize != 3 && support[s] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for face %D (fMax %D)", coneSize, support[s], fMax);
6470:         DMPlexGetCone(dm, support[s], &cone);
6471:         for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
6472:         if (coneSize == 3) supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + r;
6473:         else if (coneSize == 4) {
6474:           if (r != 0 && r != 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position in cone %D of face %D (fMax %D) for edge %D", r, support[s], fMax, e);
6475:           supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + support[s] - fMax;
6476:         } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for face %D (fMax %D)", coneSize, support[s], fMax);
6477:       }
6478:       DMPlexSetSupport(rdm, newp, supportRef);
6479: #if defined(PETSC_USE_DEBUG)
6480:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
6481:       for (p = 0; p < 2+size; ++p) {
6482:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
6483:       }
6484: #endif
6485:     }
6486:     /* Split Edges have 2 vertices and the same faces as the parent */
6487:     for (e = eStart; e < eMax; ++e) {
6488:       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);

6490:       for (r = 0; r < 2; ++r) {
6491:         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
6492:         const PetscInt *cone, *ornt, *support;
6493:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

6495:         DMPlexGetCone(dm, e, &cone);
6496:         coneNew[0]       = vStartNew + (cone[0] - vStart);
6497:         coneNew[1]       = vStartNew + (cone[1] - vStart);
6498:         coneNew[(r+1)%2] = newv;
6499:         DMPlexSetCone(rdm, newp, coneNew);
6500: #if defined(PETSC_USE_DEBUG)
6501:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6502:         for (p = 0; p < 2; ++p) {
6503:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
6504:         }
6505: #endif
6506:         DMPlexGetSupportSize(dm, e, &supportSize);
6507:         DMPlexGetSupport(dm, e, &support);
6508:         for (s = 0; s < supportSize; ++s) {
6509:           DMPlexGetConeSize(dm, support[s], &coneSize);
6510:           if (coneSize != 4 && support[s] >= fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for face %D (fMax %D)", coneSize, support[s], fMax);
6511:           if (coneSize != 3 && support[s] <  fMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for face %D (fMax %D)", coneSize, support[s], fMax);
6512:           DMPlexGetCone(dm, support[s], &cone);
6513:           DMPlexGetConeOrientation(dm, support[s], &ornt);
6514:           for (c = 0; c < coneSize; ++c) {
6515:             if (cone[c] == e) break;
6516:           }
6517:           if (coneSize == 3) supportRef[s] = fStartNew + (support[s] - fStart)*3 + (c + (ornt[c] < 0 ? 1-r : r))%3;
6518:           else if (coneSize == 4) {
6519:             if (c != 0 && c != 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position in cone %D of face %D (fMax %D) for edge %D", c, support[s], fMax, e);
6520:             supportRef[s] = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
6521:           } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for face %D (fMax %D)", coneSize, support[s], fMax);
6522:         }
6523:         DMPlexSetSupport(rdm, newp, supportRef);
6524: #if defined(PETSC_USE_DEBUG)
6525:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
6526:         for (p = 0; p < supportSize; ++p) {
6527:           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
6528:         }
6529: #endif
6530:       }
6531:     }
6532:     /* Face vertices have 3 + cells supports */
6533:     for (f = fStart; f < fMax; ++f) {
6534:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
6535:       const PetscInt *cone, *support;
6536:       PetscInt        size, s;

6538:       DMPlexGetSupportSize(dm, f, &size);
6539:       DMPlexGetSupport(dm, f, &support);
6540:       supportRef[0] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 0;
6541:       supportRef[1] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 1;
6542:       supportRef[2] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 2;
6543:       for (s = 0; s < size; ++s) {
6544:         PetscInt r, coneSize;

6546:         supportRef[3+s] = -1;
6547:         DMPlexGetConeSize(dm, support[s], &coneSize);
6548:         if (coneSize != 5 && support[s] >= cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
6549:         if (coneSize != 4 && support[s] <  cMax) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected conesize %D for cell %D (cMax %D)", coneSize, support[s], cMax);
6550:         DMPlexGetCone(dm, support[s], &cone);
6551:         for (r = 0; r < coneSize; ++r) {if (cone[r] == f) break;}
6552:         if (coneSize == 4) supportRef[3+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (support[s] - cStart)*4 + r;
6553:         else if (coneSize == 5) {
6554:           if (r != 0 && r != 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected position in cone %D of cell %D (cMax %D) for face %D", r, support[s], cMax, f);
6555:           supportRef[3+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + support[s] - cMax;
6556:         }
6557:       }
6558:       DMPlexSetSupport(rdm, newp, supportRef);
6559: #if defined(PETSC_USE_DEBUG)
6560:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
6561:       for (p = 0; p < 3+size; ++p) {
6562:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
6563:       }
6564: #endif
6565:     }
6566:     /* Interior cell vertices have 4 supports */
6567:     for (c = cStart; c < cMax; ++c) {
6568:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + c - cStart;

6570:       supportRef[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 0;
6571:       supportRef[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 1;
6572:       supportRef[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 2;
6573:       supportRef[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart)*4 + 3;
6574:       DMPlexSetSupport(rdm, newp, supportRef);
6575: #if defined(PETSC_USE_DEBUG)
6576:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
6577:       for (p = 0; p < 4; ++p) {
6578:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
6579:       }
6580: #endif
6581:     }
6582:     PetscFree(supportRef);
6583:     DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
6584:     break;
6585:   case REFINER_HEX_3D:
6586:     /*
6587:      Bottom (viewed from top)    Top
6588:      1---------2---------2       7---------2---------6
6589:      |         |         |       |         |         |
6590:      |    B    2    C    |       |    H    2    G    |
6591:      |         |         |       |         |         |
6592:      3----3----0----1----1       3----3----0----1----1
6593:      |         |         |       |         |         |
6594:      |    A    0    D    |       |    E    0    F    |
6595:      |         |         |       |         |         |
6596:      0---------0---------3       4---------0---------5
6597:      */
6598:     /* All cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
6599:     for (c = cStart; c < cEnd; ++c) {
6600:       const PetscInt  newp = (c - cStart)*8;
6601:       const PetscInt *cone, *ornt;
6602:       PetscInt        coneNew[6], orntNew[6];

6604:       DMPlexGetCone(dm, c, &cone);
6605:       DMPlexGetConeOrientation(dm, c, &ornt);
6606:       /* A hex */
6607:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
6608:       orntNew[0] = ornt[0];
6609:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
6610:       orntNew[1] = 0;
6611:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
6612:       orntNew[2] = ornt[2];
6613:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
6614:       orntNew[3] = 0;
6615:       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
6616:       orntNew[4] = 0;
6617:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
6618:       orntNew[5] = ornt[5];
6619:       DMPlexSetCone(rdm, newp+0, coneNew);
6620:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
6621: #if defined(PETSC_USE_DEBUG)
6622:       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cEndNew);
6623:       for (p = 0; p < 6; ++p) {
6624:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6625:       }
6626: #endif
6627:       /* B hex */
6628:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
6629:       orntNew[0] = ornt[0];
6630:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
6631:       orntNew[1] = 0;
6632:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
6633:       orntNew[2] = -1;
6634:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
6635:       orntNew[3] = ornt[3];
6636:       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
6637:       orntNew[4] = 0;
6638:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
6639:       orntNew[5] = ornt[5];
6640:       DMPlexSetCone(rdm, newp+1, coneNew);
6641:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
6642: #if defined(PETSC_USE_DEBUG)
6643:       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cEndNew);
6644:       for (p = 0; p < 6; ++p) {
6645:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6646:       }
6647: #endif
6648:       /* C hex */
6649:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
6650:       orntNew[0] = ornt[0];
6651:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
6652:       orntNew[1] = 0;
6653:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
6654:       orntNew[2] = -1;
6655:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
6656:       orntNew[3] = ornt[3];
6657:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
6658:       orntNew[4] = ornt[4];
6659:       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
6660:       orntNew[5] = -4;
6661:       DMPlexSetCone(rdm, newp+2, coneNew);
6662:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
6663: #if defined(PETSC_USE_DEBUG)
6664:       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cEndNew);
6665:       for (p = 0; p < 6; ++p) {
6666:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6667:       }
6668: #endif
6669:       /* D hex */
6670:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
6671:       orntNew[0] = ornt[0];
6672:       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
6673:       orntNew[1] = 0;
6674:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
6675:       orntNew[2] = ornt[2];
6676:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
6677:       orntNew[3] = 0;
6678:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
6679:       orntNew[4] = ornt[4];
6680:       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
6681:       orntNew[5] = -4;
6682:       DMPlexSetCone(rdm, newp+3, coneNew);
6683:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
6684: #if defined(PETSC_USE_DEBUG)
6685:       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cEndNew);
6686:       for (p = 0; p < 6; ++p) {
6687:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6688:       }
6689: #endif
6690:       /* E hex */
6691:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
6692:       orntNew[0] = -4;
6693:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
6694:       orntNew[1] = ornt[1];
6695:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
6696:       orntNew[2] = ornt[2];
6697:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
6698:       orntNew[3] = 0;
6699:       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
6700:       orntNew[4] = -1;
6701:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
6702:       orntNew[5] = ornt[5];
6703:       DMPlexSetCone(rdm, newp+4, coneNew);
6704:       DMPlexSetConeOrientation(rdm, newp+4, orntNew);
6705: #if defined(PETSC_USE_DEBUG)
6706:       if ((newp+4 < cStartNew) || (newp+4 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+4, cStartNew, cEndNew);
6707:       for (p = 0; p < 6; ++p) {
6708:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6709:       }
6710: #endif
6711:       /* F hex */
6712:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
6713:       orntNew[0] = -4;
6714:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
6715:       orntNew[1] = ornt[1];
6716:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
6717:       orntNew[2] = ornt[2];
6718:       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
6719:       orntNew[3] = -1;
6720:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
6721:       orntNew[4] = ornt[4];
6722:       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
6723:       orntNew[5] = 1;
6724:       DMPlexSetCone(rdm, newp+5, coneNew);
6725:       DMPlexSetConeOrientation(rdm, newp+5, orntNew);
6726: #if defined(PETSC_USE_DEBUG)
6727:       if ((newp+5 < cStartNew) || (newp+5 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+5, cStartNew, cEndNew);
6728:       for (p = 0; p < 6; ++p) {
6729:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6730:       }
6731: #endif
6732:       /* G hex */
6733:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
6734:       orntNew[0] = -4;
6735:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
6736:       orntNew[1] = ornt[1];
6737:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
6738:       orntNew[2] = 0;
6739:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
6740:       orntNew[3] = ornt[3];
6741:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
6742:       orntNew[4] = ornt[4];
6743:       coneNew[5] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
6744:       orntNew[5] = -3;
6745:       DMPlexSetCone(rdm, newp+6, coneNew);
6746:       DMPlexSetConeOrientation(rdm, newp+6, orntNew);
6747: #if defined(PETSC_USE_DEBUG)
6748:       if ((newp+6 < cStartNew) || (newp+6 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+6, cStartNew, cEndNew);
6749:       for (p = 0; p < 6; ++p) {
6750:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6751:       }
6752: #endif
6753:       /* H hex */
6754:       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
6755:       orntNew[0] = -4;
6756:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
6757:       orntNew[1] = ornt[1];
6758:       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
6759:       orntNew[2] = -1;
6760:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
6761:       orntNew[3] = ornt[3];
6762:       coneNew[4] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
6763:       orntNew[4] = 3;
6764:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
6765:       orntNew[5] = ornt[5];
6766:       DMPlexSetCone(rdm, newp+7, coneNew);
6767:       DMPlexSetConeOrientation(rdm, newp+7, orntNew);
6768: #if defined(PETSC_USE_DEBUG)
6769:       if ((newp+7 < cStartNew) || (newp+7 >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+7, cStartNew, cEndNew);
6770:       for (p = 0; p < 6; ++p) {
6771:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fEndNew);
6772:       }
6773: #endif
6774:     }
6775:     /* Split faces have 4 edges and the same cells as the parent */
6776:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
6777:     PetscMalloc1(4 + maxSupportSize*2, &supportRef);
6778:     for (f = fStart; f < fEnd; ++f) {
6779:       for (r = 0; r < 4; ++r) {
6780:         /* TODO: This can come from GetFaces_Internal() */
6781:         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};
6782:         const PetscInt  newp = fStartNew + (f - fStart)*4 + r;
6783:         const PetscInt *cone, *ornt, *support;
6784:         PetscInt        coneNew[4], orntNew[4], coneSize, c, supportSize, s;

6786:         DMPlexGetCone(dm, f, &cone);
6787:         DMPlexGetConeOrientation(dm, f, &ornt);
6788:         coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
6789:         orntNew[(r+3)%4] = ornt[(r+3)%4];
6790:         coneNew[(r+0)%4] = eStartNew + (cone[r]       - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
6791:         orntNew[(r+0)%4] = ornt[r];
6792:         coneNew[(r+1)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
6793:         orntNew[(r+1)%4] = 0;
6794:         coneNew[(r+2)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + (r+3)%4;
6795:         orntNew[(r+2)%4] = -2;
6796:         DMPlexSetCone(rdm, newp, coneNew);
6797:         DMPlexSetConeOrientation(rdm, newp, orntNew);
6798: #if defined(PETSC_USE_DEBUG)
6799:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6800:         for (p = 0; p < 4; ++p) {
6801:           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6802:         }
6803: #endif
6804:         DMPlexGetSupportSize(dm, f, &supportSize);
6805:         DMPlexGetSupport(dm, f, &support);
6806:         for (s = 0; s < supportSize; ++s) {
6807:           DMPlexGetConeSize(dm, support[s], &coneSize);
6808:           DMPlexGetCone(dm, support[s], &cone);
6809:           DMPlexGetConeOrientation(dm, support[s], &ornt);
6810:           for (c = 0; c < coneSize; ++c) {
6811:             if (cone[c] == f) break;
6812:           }
6813:           supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+GetQuadSubfaceInverse_Static(ornt[c], r)];
6814:         }
6815:         DMPlexSetSupport(rdm, newp, supportRef);
6816: #if defined(PETSC_USE_DEBUG)
6817:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6818:         for (p = 0; p < supportSize; ++p) {
6819:           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
6820:         }
6821: #endif
6822:       }
6823:     }
6824:     /* Interior faces have 4 edges and 2 cells */
6825:     for (c = cStart; c < cEnd; ++c) {
6826:       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};
6827:       const PetscInt *cone, *ornt;
6828:       PetscInt        newp, coneNew[4], orntNew[4], supportNew[2];

6830:       DMPlexGetCone(dm, c, &cone);
6831:       DMPlexGetConeOrientation(dm, c, &ornt);
6832:       /* A-D face */
6833:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0;
6834:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
6835:       orntNew[0] = 0;
6836:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
6837:       orntNew[1] = 0;
6838:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
6839:       orntNew[2] = -2;
6840:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
6841:       orntNew[3] = -2;
6842:       DMPlexSetCone(rdm, newp, coneNew);
6843:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6844: #if defined(PETSC_USE_DEBUG)
6845:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6846:       for (p = 0; p < 4; ++p) {
6847:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6848:       }
6849: #endif
6850:       /* C-D face */
6851:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1;
6852:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
6853:       orntNew[0] = 0;
6854:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
6855:       orntNew[1] = 0;
6856:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
6857:       orntNew[2] = -2;
6858:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
6859:       orntNew[3] = -2;
6860:       DMPlexSetCone(rdm, newp, coneNew);
6861:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6862: #if defined(PETSC_USE_DEBUG)
6863:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6864:       for (p = 0; p < 4; ++p) {
6865:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6866:       }
6867: #endif
6868:       /* B-C face */
6869:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2;
6870:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
6871:       orntNew[0] = -2;
6872:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
6873:       orntNew[1] = 0;
6874:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
6875:       orntNew[2] = 0;
6876:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
6877:       orntNew[3] = -2;
6878:       DMPlexSetCone(rdm, newp, coneNew);
6879:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6880: #if defined(PETSC_USE_DEBUG)
6881:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6882:       for (p = 0; p < 4; ++p) {
6883:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6884:       }
6885: #endif
6886:       /* A-B face */
6887:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3;
6888:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
6889:       orntNew[0] = -2;
6890:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
6891:       orntNew[1] = 0;
6892:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
6893:       orntNew[2] = 0;
6894:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 0;
6895:       orntNew[3] = -2;
6896:       DMPlexSetCone(rdm, newp, coneNew);
6897:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6898: #if defined(PETSC_USE_DEBUG)
6899:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6900:       for (p = 0; p < 4; ++p) {
6901:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6902:       }
6903: #endif
6904:       /* E-F face */
6905:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4;
6906:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
6907:       orntNew[0] = -2;
6908:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
6909:       orntNew[1] = -2;
6910:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
6911:       orntNew[2] = 0;
6912:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
6913:       orntNew[3] = 0;
6914:       DMPlexSetCone(rdm, newp, coneNew);
6915:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6916: #if defined(PETSC_USE_DEBUG)
6917:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6918:       for (p = 0; p < 4; ++p) {
6919:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6920:       }
6921: #endif
6922:       /* F-G face */
6923:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5;
6924:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
6925:       orntNew[0] = -2;
6926:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
6927:       orntNew[1] = -2;
6928:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
6929:       orntNew[2] = 0;
6930:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
6931:       orntNew[3] = 0;
6932:       DMPlexSetCone(rdm, newp, coneNew);
6933:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6934: #if defined(PETSC_USE_DEBUG)
6935:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6936:       for (p = 0; p < 4; ++p) {
6937:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6938:       }
6939: #endif
6940:       /* G-H face */
6941:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6;
6942:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
6943:       orntNew[0] = -2;
6944:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
6945:       orntNew[1] = 0;
6946:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
6947:       orntNew[2] = 0;
6948:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
6949:       orntNew[3] = -2;
6950:       DMPlexSetCone(rdm, newp, coneNew);
6951:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6952: #if defined(PETSC_USE_DEBUG)
6953:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6954:       for (p = 0; p < 4; ++p) {
6955:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6956:       }
6957: #endif
6958:       /* E-H face */
6959:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7;
6960:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
6961:       orntNew[0] = -2;
6962:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
6963:       orntNew[1] = -2;
6964:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
6965:       orntNew[2] = 0;
6966:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 1;
6967:       orntNew[3] = 0;
6968:       DMPlexSetCone(rdm, newp, coneNew);
6969:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6970: #if defined(PETSC_USE_DEBUG)
6971:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6972:       for (p = 0; p < 4; ++p) {
6973:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6974:       }
6975: #endif
6976:       /* A-E face */
6977:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8;
6978:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
6979:       orntNew[0] = 0;
6980:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
6981:       orntNew[1] = 0;
6982:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
6983:       orntNew[2] = -2;
6984:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
6985:       orntNew[3] = -2;
6986:       DMPlexSetCone(rdm, newp, coneNew);
6987:       DMPlexSetConeOrientation(rdm, newp, orntNew);
6988: #if defined(PETSC_USE_DEBUG)
6989:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
6990:       for (p = 0; p < 4; ++p) {
6991:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
6992:       }
6993: #endif
6994:       /* D-F face */
6995:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9;
6996:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
6997:       orntNew[0] = -2;
6998:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
6999:       orntNew[1] = 0;
7000:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
7001:       orntNew[2] = 0;
7002:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 2;
7003:       orntNew[3] = -2;
7004:       DMPlexSetCone(rdm, newp, coneNew);
7005:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7006: #if defined(PETSC_USE_DEBUG)
7007:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
7008:       for (p = 0; p < 4; ++p) {
7009:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
7010:       }
7011: #endif
7012:       /* C-G face */
7013:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10;
7014:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 4;
7015:       orntNew[0] = -2;
7016:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
7017:       orntNew[1] = -2;
7018:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
7019:       orntNew[2] = 0;
7020:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
7021:       orntNew[3] = 0;
7022:       DMPlexSetCone(rdm, newp, coneNew);
7023:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7024: #if defined(PETSC_USE_DEBUG)
7025:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
7026:       for (p = 0; p < 4; ++p) {
7027:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
7028:       }
7029: #endif
7030:       /* B-H face */
7031:       newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11;
7032:       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 5;
7033:       orntNew[0] = 0;
7034:       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd    - fStart)*4 + (c - cStart)*6 + 3;
7035:       orntNew[1] = -2;
7036:       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
7037:       orntNew[2] = -2;
7038:       coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
7039:       orntNew[3] = 0;
7040:       DMPlexSetCone(rdm, newp, coneNew);
7041:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7042: #if defined(PETSC_USE_DEBUG)
7043:       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
7044:       for (p = 0; p < 4; ++p) {
7045:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eEndNew);
7046:       }
7047: #endif
7048:       for (r = 0; r < 12; ++r) {
7049:         newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
7050:         supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
7051:         supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
7052:         DMPlexSetSupport(rdm, newp, supportNew);
7053: #if defined(PETSC_USE_DEBUG)
7054:         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fEndNew);
7055:         for (p = 0; p < 2; ++p) {
7056:           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cEndNew);
7057:         }
7058: #endif
7059:       }
7060:     }
7061:     /* Split edges have 2 vertices and the same faces as the parent */
7062:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
7063:     for (e = eStart; e < eEnd; ++e) {
7064:       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);

7066:       for (r = 0; r < 2; ++r) {
7067:         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
7068:         const PetscInt *cone, *ornt, *support;
7069:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

7071:         DMPlexGetCone(dm, e, &cone);
7072:         coneNew[0]       = vStartNew + (cone[0] - vStart);
7073:         coneNew[1]       = vStartNew + (cone[1] - vStart);
7074:         coneNew[(r+1)%2] = newv;
7075:         DMPlexSetCone(rdm, newp, coneNew);
7076: #if defined(PETSC_USE_DEBUG)
7077:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
7078:         for (p = 0; p < 2; ++p) {
7079:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
7080:         }
7081: #endif
7082:         DMPlexGetSupportSize(dm, e, &supportSize);
7083:         DMPlexGetSupport(dm, e, &support);
7084:         for (s = 0; s < supportSize; ++s) {
7085:           DMPlexGetConeSize(dm, support[s], &coneSize);
7086:           DMPlexGetCone(dm, support[s], &cone);
7087:           DMPlexGetConeOrientation(dm, support[s], &ornt);
7088:           for (c = 0; c < coneSize; ++c) {
7089:             if (cone[c] == e) break;
7090:           }
7091:           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
7092:         }
7093:         DMPlexSetSupport(rdm, newp, supportRef);
7094: #if defined(PETSC_USE_DEBUG)
7095:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
7096:         for (p = 0; p < supportSize; ++p) {
7097:           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
7098:         }
7099: #endif
7100:       }
7101:     }
7102:     /* Face edges have 2 vertices and 2+cells faces */
7103:     for (f = fStart; f < fEnd; ++f) {
7104:       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};
7105:       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
7106:       const PetscInt *cone, *coneCell, *orntCell, *support;
7107:       PetscInt        coneNew[2], coneSize, c, supportSize, s;

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

7113:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
7114:         coneNew[1] = newv;
7115:         DMPlexSetCone(rdm, newp, coneNew);
7116: #if defined(PETSC_USE_DEBUG)
7117:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
7118:         for (p = 0; p < 2; ++p) {
7119:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
7120:         }
7121: #endif
7122:         DMPlexGetSupportSize(dm, f, &supportSize);
7123:         DMPlexGetSupport(dm, f, &support);
7124:         supportRef[0] = fStartNew + (f - fStart)*4 + r;
7125:         supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
7126:         for (s = 0; s < supportSize; ++s) {
7127:           DMPlexGetConeSize(dm, support[s], &coneSize);
7128:           DMPlexGetCone(dm, support[s], &coneCell);
7129:           DMPlexGetConeOrientation(dm, support[s], &orntCell);
7130:           for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
7131:           supportRef[2+s] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
7132:         }
7133:         DMPlexSetSupport(rdm, newp, supportRef);
7134: #if defined(PETSC_USE_DEBUG)
7135:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
7136:         for (p = 0; p < 2+supportSize; ++p) {
7137:           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
7138:         }
7139: #endif
7140:       }
7141:     }
7142:     /* Cell edges have 2 vertices and 4 faces */
7143:     for (c = cStart; c < cEnd; ++c) {
7144:       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};
7145:       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
7146:       const PetscInt *cone;
7147:       PetscInt        coneNew[2], supportNew[4];

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

7153:         coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
7154:         coneNew[1] = newv;
7155:         DMPlexSetCone(rdm, newp, coneNew);
7156: #if defined(PETSC_USE_DEBUG)
7157:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
7158:         for (p = 0; p < 2; ++p) {
7159:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
7160:         }
7161: #endif
7162:         for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
7163:         DMPlexSetSupport(rdm, newp, supportNew);
7164: #if defined(PETSC_USE_DEBUG)
7165:         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eEndNew);
7166:         for (p = 0; p < 4; ++p) {
7167:           if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fEndNew);
7168:         }
7169: #endif
7170:       }
7171:     }
7172:     /* Old vertices have identical supports */
7173:     for (v = vStart; v < vEnd; ++v) {
7174:       const PetscInt  newp = vStartNew + (v - vStart);
7175:       const PetscInt *support, *cone;
7176:       PetscInt        size, s;

7178:       DMPlexGetSupportSize(dm, v, &size);
7179:       DMPlexGetSupport(dm, v, &support);
7180:       for (s = 0; s < size; ++s) {
7181:         PetscInt r = 0;

7183:         DMPlexGetCone(dm, support[s], &cone);
7184:         if (cone[1] == v) r = 1;
7185:         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
7186:       }
7187:       DMPlexSetSupport(rdm, newp, supportRef);
7188: #if defined(PETSC_USE_DEBUG)
7189:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
7190:       for (p = 0; p < size; ++p) {
7191:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
7192:       }
7193: #endif
7194:     }
7195:     /* Edge vertices have 2 + faces supports */
7196:     for (e = eStart; e < eEnd; ++e) {
7197:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
7198:       const PetscInt *cone, *support;
7199:       PetscInt        size, s;

7201:       DMPlexGetSupportSize(dm, e, &size);
7202:       DMPlexGetSupport(dm, e, &support);
7203:       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
7204:       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
7205:       for (s = 0; s < size; ++s) {
7206:         PetscInt r;

7208:         DMPlexGetCone(dm, support[s], &cone);
7209:         for (r = 0; r < 4; ++r) if (cone[r] == e) break;
7210:         supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*4 + r;
7211:       }
7212:       DMPlexSetSupport(rdm, newp, supportRef);
7213: #if defined(PETSC_USE_DEBUG)
7214:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
7215:       for (p = 0; p < 2+size; ++p) {
7216:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
7217:       }
7218: #endif
7219:     }
7220:     /* Face vertices have 4 + cells supports */
7221:     for (f = fStart; f < fEnd; ++f) {
7222:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
7223:       const PetscInt *cone, *support;
7224:       PetscInt        size, s;

7226:       DMPlexGetSupportSize(dm, f, &size);
7227:       DMPlexGetSupport(dm, f, &support);
7228:       for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eEnd - eStart)*2 +  (f - fStart)*4 + r;
7229:       for (s = 0; s < size; ++s) {
7230:         PetscInt r;

7232:         DMPlexGetCone(dm, support[s], &cone);
7233:         for (r = 0; r < 6; ++r) if (cone[r] == f) break;
7234:         supportRef[4+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (support[s] - cStart)*6 + r;
7235:       }
7236:       DMPlexSetSupport(rdm, newp, supportRef);
7237: #if defined(PETSC_USE_DEBUG)
7238:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
7239:       for (p = 0; p < 4+size; ++p) {
7240:         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", supportRef[p], eStartNew, eEndNew);
7241:       }
7242: #endif
7243:     }
7244:     /* Cell vertices have 6 supports */
7245:     for (c = cStart; c < cEnd; ++c) {
7246:       const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
7247:       PetscInt       supportNew[6];

7249:       for (r = 0; r < 6; ++r) {
7250:         supportNew[r] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
7251:       }
7252:       DMPlexSetSupport(rdm, newp, supportNew);
7253:     }
7254:     PetscFree(supportRef);
7255:     break;
7256:   case REFINER_HYBRID_HEX_3D:
7257:     DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);
7258:     /*
7259:      Bottom (viewed from top)    Top
7260:      1---------2---------2       7---------2---------6
7261:      |         |         |       |         |         |
7262:      |    B    2    C    |       |    H    2    G    |
7263:      |         |         |       |         |         |
7264:      3----3----0----1----1       3----3----0----1----1
7265:      |         |         |       |         |         |
7266:      |    A    0    D    |       |    E    0    F    |
7267:      |         |         |       |         |         |
7268:      0---------0---------3       4---------0---------5
7269:      */
7270:     /* Interior cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
7271:     for (c = cStart; c < cMax; ++c) {
7272:       const PetscInt  newp = (c - cStart)*8;
7273:       const PetscInt *cone, *ornt;
7274:       PetscInt        coneNew[6], orntNew[6];

7276:       DMPlexGetCone(dm, c, &cone);
7277:       DMPlexGetConeOrientation(dm, c, &ornt);
7278:       /* A hex */
7279:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
7280:       orntNew[0] = ornt[0];
7281:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
7282:       orntNew[1] = 0;
7283:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
7284:       orntNew[2] = ornt[2];
7285:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
7286:       orntNew[3] = 0;
7287:       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
7288:       orntNew[4] = 0;
7289:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
7290:       orntNew[5] = ornt[5];
7291:       DMPlexSetCone(rdm, newp+0, coneNew);
7292:       DMPlexSetConeOrientation(rdm, newp+0, orntNew);
7293: #if defined(PETSC_USE_DEBUG)
7294:       if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+0, cStartNew, cMaxNew);
7295:       for (p = 0; p < 6; ++p) {
7296:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7297:       }
7298: #endif
7299:       /* B hex */
7300:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
7301:       orntNew[0] = ornt[0];
7302:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
7303:       orntNew[1] = 0;
7304:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  3; /* AB */
7305:       orntNew[2] = -1;
7306:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
7307:       orntNew[3] = ornt[3];
7308:       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
7309:       orntNew[4] = 0;
7310:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
7311:       orntNew[5] = ornt[5];
7312:       DMPlexSetCone(rdm, newp+1, coneNew);
7313:       DMPlexSetConeOrientation(rdm, newp+1, orntNew);
7314: #if defined(PETSC_USE_DEBUG)
7315:       if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+1, cStartNew, cMaxNew);
7316:       for (p = 0; p < 6; ++p) {
7317:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7318:       }
7319: #endif
7320:       /* C hex */
7321:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
7322:       orntNew[0] = ornt[0];
7323:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
7324:       orntNew[1] = 0;
7325:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
7326:       orntNew[2] = -1;
7327:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
7328:       orntNew[3] = ornt[3];
7329:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
7330:       orntNew[4] = ornt[4];
7331:       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  2; /* BC */
7332:       orntNew[5] = -4;
7333:       DMPlexSetCone(rdm, newp+2, coneNew);
7334:       DMPlexSetConeOrientation(rdm, newp+2, orntNew);
7335: #if defined(PETSC_USE_DEBUG)
7336:       if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+2, cStartNew, cMaxNew);
7337:       for (p = 0; p < 6; ++p) {
7338:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7339:       }
7340: #endif
7341:       /* D hex */
7342:       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
7343:       orntNew[0] = ornt[0];
7344:       coneNew[1] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
7345:       orntNew[1] = 0;
7346:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
7347:       orntNew[2] = ornt[2];
7348:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  1; /* CD */
7349:       orntNew[3] = 0;
7350:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
7351:       orntNew[4] = ornt[4];
7352:       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  0; /* AD */
7353:       orntNew[5] = -4;
7354:       DMPlexSetCone(rdm, newp+3, coneNew);
7355:       DMPlexSetConeOrientation(rdm, newp+3, orntNew);
7356: #if defined(PETSC_USE_DEBUG)
7357:       if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+3, cStartNew, cMaxNew);
7358:       for (p = 0; p < 6; ++p) {
7359:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7360:       }
7361: #endif
7362:       /* E hex */
7363:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  8; /* AE */
7364:       orntNew[0] = -4;
7365:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
7366:       orntNew[1] = ornt[1];
7367:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
7368:       orntNew[2] = ornt[2];
7369:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
7370:       orntNew[3] = 0;
7371:       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
7372:       orntNew[4] = -1;
7373:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
7374:       orntNew[5] = ornt[5];
7375:       DMPlexSetCone(rdm, newp+4, coneNew);
7376:       DMPlexSetConeOrientation(rdm, newp+4, orntNew);
7377: #if defined(PETSC_USE_DEBUG)
7378:       if ((newp+4 < cStartNew) || (newp+4 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+4, cStartNew, cMaxNew);
7379:       for (p = 0; p < 6; ++p) {
7380:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7381:       }
7382: #endif
7383:       /* F hex */
7384:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  9; /* DF */
7385:       orntNew[0] = -4;
7386:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
7387:       orntNew[1] = ornt[1];
7388:       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
7389:       orntNew[2] = ornt[2];
7390:       coneNew[3] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
7391:       orntNew[3] = -1;
7392:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
7393:       orntNew[4] = ornt[4];
7394:       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  4; /* EF */
7395:       orntNew[5] = 1;
7396:       DMPlexSetCone(rdm, newp+5, coneNew);
7397:       DMPlexSetConeOrientation(rdm, newp+5, orntNew);
7398: #if defined(PETSC_USE_DEBUG)
7399:       if ((newp+5 < cStartNew) || (newp+5 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+5, cStartNew, cMaxNew);
7400:       for (p = 0; p < 6; ++p) {
7401:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7402:       }
7403: #endif
7404:       /* G hex */
7405:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 10; /* CG */
7406:       orntNew[0] = -4;
7407:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
7408:       orntNew[1] = ornt[1];
7409:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  5; /* FG */
7410:       orntNew[2] = 0;
7411:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
7412:       orntNew[3] = ornt[3];
7413:       coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
7414:       orntNew[4] = ornt[4];
7415:       coneNew[5] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
7416:       orntNew[5] = -3;
7417:       DMPlexSetCone(rdm, newp+6, coneNew);
7418:       DMPlexSetConeOrientation(rdm, newp+6, orntNew);
7419: #if defined(PETSC_USE_DEBUG)
7420:       if ((newp+6 < cStartNew) || (newp+6 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+6, cStartNew, cMaxNew);
7421:       for (p = 0; p < 6; ++p) {
7422:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7423:       }
7424: #endif
7425:       /* H hex */
7426:       coneNew[0] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 + 11; /* BH */
7427:       orntNew[0] = -4;
7428:       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
7429:       orntNew[1] = ornt[1];
7430:       coneNew[2] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  7; /* EH */
7431:       orntNew[2] = -1;
7432:       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
7433:       orntNew[3] = ornt[3];
7434:       coneNew[4] = fStartNew + (fMax    - fStart)*4 + (c - cStart)*12 +  6; /* GH */
7435:       orntNew[4] = 3;
7436:       coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
7437:       orntNew[5] = ornt[5];
7438:       DMPlexSetCone(rdm, newp+7, coneNew);
7439:       DMPlexSetConeOrientation(rdm, newp+7, orntNew);
7440: #if defined(PETSC_USE_DEBUG)
7441:       if ((newp+7 < cStartNew) || (newp+7 >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", newp+7, cStartNew, cMaxNew);
7442:       for (p = 0; p < 6; ++p) {
7443:         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7444:       }
7445: #endif
7446:     }
7447:     /* Hybrid cells have 6 faces: Front, Back, Sides */
7448:     /*
7449:      3---------2---------2
7450:      |         |         |
7451:      |    D    2    C    |
7452:      |         |         |
7453:      3----3----0----1----1
7454:      |         |         |
7455:      |    A    0    B    |
7456:      |         |         |
7457:      0---------0---------1
7458:      */
7459:     for (c = cMax; c < cEnd; ++c) {
7460:       const PetscInt  newp = (cMax - cStart)*8 + (c - cMax)*4;
7461:       const PetscInt *cone, *ornt, *fornt;
7462:       PetscInt        coneNew[6], orntNew[6], o, of, i;

7464:       DMPlexGetCone(dm, c, &cone);
7465:       DMPlexGetConeOrientation(dm, c, &ornt);
7466:       DMPlexGetConeOrientation(dm, cone[0], &fornt);
7467:       o = ornt[0] < 0 ? -1 : 1;
7468:       for (r = 0; r < 4; ++r) {
7469:         PetscInt subfA = GetQuadSubface_Static(ornt[0], r);
7470:         PetscInt edgeA = GetQuadEdge_Static(ornt[0], r);
7471:         PetscInt edgeB = GetQuadEdge_Static(ornt[0], (r+3)%4);
7472:         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]);
7473:         coneNew[0]         = fStartNew + (cone[0] - fStart)*4 + subfA;
7474:         orntNew[0]         = ornt[0];
7475:         coneNew[1]         = fStartNew + (cone[1] - fStart)*4 + subfA;
7476:         orntNew[1]         = ornt[0];
7477:         of = fornt[edgeA] < 0 ? -1 : 1;
7478:         i  = GetQuadEdgeInverse_Static(ornt[0], r) + 2;
7479:         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[2+edgeA] - fMax)*2 + (o*of < 0 ? 1 : 0);
7480:         orntNew[i] = ornt[edgeA];
7481:         i  = GetQuadEdgeInverse_Static(ornt[0], (r+1)%4) + 2;
7482:         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd          - fMax)*2 + (c - cMax)*4 + edgeA;
7483:         orntNew[i] = 0;
7484:         i  = GetQuadEdgeInverse_Static(ornt[0], (r+2)%4) + 2;
7485:         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd          - fMax)*2 + (c - cMax)*4 + edgeB;
7486:         orntNew[i] = -2;
7487:         of = fornt[edgeB] < 0 ? -1 : 1;
7488:         i  = GetQuadEdgeInverse_Static(ornt[0], (r+3)%4) + 2;
7489:         coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[2+edgeB] - fMax)*2 + (o*of < 0 ? 0 : 1);
7490:         orntNew[i] = ornt[edgeB];
7491:         DMPlexSetCone(rdm, newp+r, coneNew);
7492:         DMPlexSetConeOrientation(rdm, newp+r, orntNew);
7493: #if defined(PETSC_USE_DEBUG)
7494:         if ((newp+r < cMaxNew) || (newp+r >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", newp+r, cMaxNew, cEndNew);
7495:         for (p = 0; p < 2; ++p) {
7496:           if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", coneNew[p], fStartNew, fMaxNew);
7497:         }
7498:         for (p = 2; p < 6; ++p) {
7499:           if ((coneNew[p] < fMaxNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", coneNew[p], fMaxNew, fEndNew);
7500:         }
7501: #endif
7502:       }
7503:     }
7504:     /* Interior split faces have 4 edges and the same cells as the parent */
7505:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
7506:     PetscMalloc1(4 + maxSupportSize*2, &supportRef);
7507:     for (f = fStart; f < fMax; ++f) {
7508:       for (r = 0; r < 4; ++r) {
7509:         /* TODO: This can come from GetFaces_Internal() */
7510:         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};
7511:         const PetscInt  newp = fStartNew + (f - fStart)*4 + r;
7512:         const PetscInt *cone, *ornt, *support;
7513:         PetscInt        coneNew[4], orntNew[4], coneSize, c, supportSize, s;

7515:         DMPlexGetCone(dm, f, &cone);
7516:         DMPlexGetConeOrientation(dm, f, &ornt);
7517:         coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
7518:         orntNew[(r+3)%4] = ornt[(r+3)%4];
7519:         coneNew[(r+0)%4] = eStartNew + (cone[r]       - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
7520:         orntNew[(r+0)%4] = ornt[r];
7521:         coneNew[(r+1)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
7522:         orntNew[(r+1)%4] = 0;
7523:         coneNew[(r+2)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + (r+3)%4;
7524:         orntNew[(r+2)%4] = -2;
7525:         DMPlexSetCone(rdm, newp, coneNew);
7526:         DMPlexSetConeOrientation(rdm, newp, orntNew);
7527: #if defined(PETSC_USE_DEBUG)
7528:         if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7529:         for (p = 0; p < 4; ++p) {
7530:           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7531:         }
7532: #endif
7533:         DMPlexGetSupportSize(dm, f, &supportSize);
7534:         DMPlexGetSupport(dm, f, &support);
7535:         for (s = 0; s < supportSize; ++s) {
7536:           PetscInt subf;
7537:           DMPlexGetConeSize(dm, support[s], &coneSize);
7538:           DMPlexGetCone(dm, support[s], &cone);
7539:           DMPlexGetConeOrientation(dm, support[s], &ornt);
7540:           for (c = 0; c < coneSize; ++c) {
7541:             if (cone[c] == f) break;
7542:           }
7543:           subf = GetQuadSubfaceInverse_Static(ornt[c], r);
7544:           if (support[s] < cMax) {
7545:             supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+subf];
7546:           } else {
7547:             supportRef[s] = cStartNew + (cMax       - cStart)*8 + (support[s] - cMax)*4 + subf;
7548:           }
7549:         }
7550:         DMPlexSetSupport(rdm, newp, supportRef);
7551: #if defined(PETSC_USE_DEBUG)
7552:         if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7553:         for (p = 0; p < supportSize; ++p) {
7554:           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportRef[p], cStartNew, cEndNew);
7555:         }
7556: #endif
7557:       }
7558:     }
7559:     /* Interior cell faces have 4 edges and 2 cells */
7560:     for (c = cStart; c < cMax; ++c) {
7561:       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};
7562:       const PetscInt *cone, *ornt;
7563:       PetscInt        newp, coneNew[4], orntNew[4], supportNew[2];

7565:       DMPlexGetCone(dm, c, &cone);
7566:       DMPlexGetConeOrientation(dm, c, &ornt);
7567:       /* A-D face */
7568:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 0;
7569:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
7570:       orntNew[0] = 0;
7571:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
7572:       orntNew[1] = 0;
7573:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
7574:       orntNew[2] = -2;
7575:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
7576:       orntNew[3] = -2;
7577:       DMPlexSetCone(rdm, newp, coneNew);
7578:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7579: #if defined(PETSC_USE_DEBUG)
7580:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7581:       for (p = 0; p < 4; ++p) {
7582:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7583:       }
7584: #endif
7585:       /* C-D face */
7586:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 1;
7587:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
7588:       orntNew[0] = 0;
7589:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
7590:       orntNew[1] = 0;
7591:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
7592:       orntNew[2] = -2;
7593:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
7594:       orntNew[3] = -2;
7595:       DMPlexSetCone(rdm, newp, coneNew);
7596:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7597: #if defined(PETSC_USE_DEBUG)
7598:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7599:       for (p = 0; p < 4; ++p) {
7600:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7601:       }
7602: #endif
7603:       /* B-C face */
7604:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 2;
7605:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
7606:       orntNew[0] = -2;
7607:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
7608:       orntNew[1] = 0;
7609:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
7610:       orntNew[2] = 0;
7611:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
7612:       orntNew[3] = -2;
7613:       DMPlexSetCone(rdm, newp, coneNew);
7614:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7615: #if defined(PETSC_USE_DEBUG)
7616:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7617:       for (p = 0; p < 4; ++p) {
7618:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7619:       }
7620: #endif
7621:       /* A-B face */
7622:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 3;
7623:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
7624:       orntNew[0] = -2;
7625:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
7626:       orntNew[1] = 0;
7627:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
7628:       orntNew[2] = 0;
7629:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 0;
7630:       orntNew[3] = -2;
7631:       DMPlexSetCone(rdm, newp, coneNew);
7632:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7633: #if defined(PETSC_USE_DEBUG)
7634:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7635:       for (p = 0; p < 4; ++p) {
7636:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7637:       }
7638: #endif
7639:       /* E-F face */
7640:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 4;
7641:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
7642:       orntNew[0] = -2;
7643:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
7644:       orntNew[1] = -2;
7645:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
7646:       orntNew[2] = 0;
7647:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
7648:       orntNew[3] = 0;
7649:       DMPlexSetCone(rdm, newp, coneNew);
7650:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7651: #if defined(PETSC_USE_DEBUG)
7652:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7653:       for (p = 0; p < 4; ++p) {
7654:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7655:       }
7656: #endif
7657:       /* F-G face */
7658:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 5;
7659:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
7660:       orntNew[0] = -2;
7661:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
7662:       orntNew[1] = -2;
7663:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
7664:       orntNew[2] = 0;
7665:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
7666:       orntNew[3] = 0;
7667:       DMPlexSetCone(rdm, newp, coneNew);
7668:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7669: #if defined(PETSC_USE_DEBUG)
7670:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7671:       for (p = 0; p < 4; ++p) {
7672:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7673:       }
7674: #endif
7675:       /* G-H face */
7676:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 6;
7677:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
7678:       orntNew[0] = -2;
7679:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
7680:       orntNew[1] = 0;
7681:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
7682:       orntNew[2] = 0;
7683:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
7684:       orntNew[3] = -2;
7685:       DMPlexSetCone(rdm, newp, coneNew);
7686:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7687: #if defined(PETSC_USE_DEBUG)
7688:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7689:       for (p = 0; p < 4; ++p) {
7690:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7691:       }
7692: #endif
7693:       /* E-H face */
7694:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 7;
7695:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
7696:       orntNew[0] = -2;
7697:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
7698:       orntNew[1] = -2;
7699:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
7700:       orntNew[2] = 0;
7701:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 1;
7702:       orntNew[3] = 0;
7703:       DMPlexSetCone(rdm, newp, coneNew);
7704:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7705: #if defined(PETSC_USE_DEBUG)
7706:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7707:       for (p = 0; p < 4; ++p) {
7708:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7709:       }
7710: #endif
7711:       /* A-E face */
7712:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 8;
7713:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
7714:       orntNew[0] = 0;
7715:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
7716:       orntNew[1] = 0;
7717:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
7718:       orntNew[2] = -2;
7719:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
7720:       orntNew[3] = -2;
7721:       DMPlexSetCone(rdm, newp, coneNew);
7722:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7723: #if defined(PETSC_USE_DEBUG)
7724:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7725:       for (p = 0; p < 4; ++p) {
7726:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7727:       }
7728: #endif
7729:       /* D-F face */
7730:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 9;
7731:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
7732:       orntNew[0] = -2;
7733:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
7734:       orntNew[1] = 0;
7735:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
7736:       orntNew[2] = 0;
7737:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 2;
7738:       orntNew[3] = -2;
7739:       DMPlexSetCone(rdm, newp, coneNew);
7740:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7741: #if defined(PETSC_USE_DEBUG)
7742:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7743:       for (p = 0; p < 4; ++p) {
7744:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7745:       }
7746: #endif
7747:       /* C-G face */
7748:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 10;
7749:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 4;
7750:       orntNew[0] = -2;
7751:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
7752:       orntNew[1] = -2;
7753:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
7754:       orntNew[2] = 0;
7755:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
7756:       orntNew[3] = 0;
7757:       DMPlexSetCone(rdm, newp, coneNew);
7758:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7759: #if defined(PETSC_USE_DEBUG)
7760:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7761:       for (p = 0; p < 4; ++p) {
7762:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7763:       }
7764: #endif
7765:       /* B-H face */
7766:       newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 11;
7767:       coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 5;
7768:       orntNew[0] = 0;
7769:       coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax    - fStart)*4 + (c - cStart)*6 + 3;
7770:       orntNew[1] = -2;
7771:       coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
7772:       orntNew[2] = -2;
7773:       coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
7774:       orntNew[3] = 0;
7775:       DMPlexSetCone(rdm, newp, coneNew);
7776:       DMPlexSetConeOrientation(rdm, newp, orntNew);
7777: #if defined(PETSC_USE_DEBUG)
7778:       if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7779:       for (p = 0; p < 4; ++p) {
7780:         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7781:       }
7782: #endif
7783:       for (r = 0; r < 12; ++r) {
7784:         newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + r;
7785:         supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
7786:         supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
7787:         DMPlexSetSupport(rdm, newp, supportNew);
7788: #if defined(PETSC_USE_DEBUG)
7789:         if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", newp, fStartNew, fMaxNew);
7790:         for (p = 0; p < 2; ++p) {
7791:           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a cell [%D, %D)", supportNew[p], cStartNew, cMaxNew);
7792:         }
7793: #endif
7794:       }
7795:     }
7796:     /* Hybrid split faces have 4 edges and same cells */
7797:     for (f = fMax; f < fEnd; ++f) {
7798:       const PetscInt *cone, *ornt, *support;
7799:       PetscInt        coneNew[4], orntNew[4];
7800:       PetscInt        supportNew[2], size, s, c;

7802:       DMPlexGetCone(dm, f, &cone);
7803:       DMPlexGetConeOrientation(dm, f, &ornt);
7804:       DMPlexGetSupportSize(dm, f, &size);
7805:       DMPlexGetSupport(dm, f, &support);
7806:       for (r = 0; r < 2; ++r) {
7807:         const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + r;

7809:         coneNew[0]   = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
7810:         orntNew[0]   = ornt[0];
7811:         coneNew[1]   = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
7812:         orntNew[1]   = ornt[1];
7813:         coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (cone[2+r] - eMax);
7814:         orntNew[2+r] = 0;
7815:         coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd      - eMax) + (f - fMax);
7816:         orntNew[3-r] = 0;
7817:         DMPlexSetCone(rdm, newp, coneNew);
7818:         DMPlexSetConeOrientation(rdm, newp, orntNew);
7819: #if defined(PETSC_USE_DEBUG)
7820:         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp, fMaxNew, fEndNew);
7821:         for (p = 0; p < 2; ++p) {
7822:           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7823:         }
7824:         for (p = 2; p < 4; ++p) {
7825:           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", coneNew[p], eMaxNew, eEndNew);
7826:         }
7827: #endif
7828:         for (s = 0; s < size; ++s) {
7829:           const PetscInt *coneCell, *orntCell, *fornt;
7830:           PetscInt        o, of;

7832:           DMPlexGetCone(dm, support[s], &coneCell);
7833:           DMPlexGetConeOrientation(dm, support[s], &orntCell);
7834:           o = orntCell[0] < 0 ? -1 : 1;
7835:           for (c = 2; c < 6; ++c) if (coneCell[c] == f) break;
7836:           if (c >= 6) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %D in cone of cell %D", f, support[s]);
7837:           DMPlexGetConeOrientation(dm, coneCell[0], &fornt);
7838:           of = fornt[c-2] < 0 ? -1 : 1;
7839:           supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetQuadEdgeInverse_Static(orntCell[0], c-2) + (o*of < 0 ? 1-r : r))%4;
7840:         }
7841:         DMPlexSetSupport(rdm, newp, supportNew);
7842: #if defined(PETSC_USE_DEBUG)
7843:         if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp, fMaxNew, fEndNew);
7844:         for (p = 0; p < size; ++p) {
7845:           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", supportNew[p], cMaxNew, cEndNew);
7846:         }
7847: #endif
7848:       }
7849:     }
7850:     /* Hybrid cell faces have 4 edges and 2 cells */
7851:     for (c = cMax; c < cEnd; ++c) {
7852:       PetscInt        newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4;
7853:       const PetscInt *cone, *ornt;
7854:       PetscInt        coneNew[4], orntNew[4];
7855:       PetscInt        supportNew[2];

7857:       DMPlexGetCone(dm, c, &cone);
7858:       DMPlexGetConeOrientation(dm, c, &ornt);
7859:       for (r = 0; r < 4; ++r) {
7860: #if 0
7861:         coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], r);
7862:         orntNew[0] = 0;
7863:         coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], r);
7864:         orntNew[1] = 0;
7865:         coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (cone[2+GetQuadEdge_Static(ornt[0], r)] - fMax);
7866:         orntNew[2] = 0;
7867:         coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd                                   - fMax) + (c - cMax);
7868:         orntNew[3] = 0;
7869: #else
7870:         coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + r;
7871:         orntNew[0] = 0;
7872:         coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + r;
7873:         orntNew[1] = 0;
7874:         coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (cone[2+r] - fMax);
7875:         orntNew[2] = 0;
7876:         coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd      - fMax) + (c - cMax);
7877:         orntNew[3] = 0;
7878: #endif
7879:         DMPlexSetCone(rdm, newp+r, coneNew);
7880:         DMPlexSetConeOrientation(rdm, newp+r, orntNew);
7881: #if defined(PETSC_USE_DEBUG)
7882:         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp+r, fMaxNew, fEndNew);
7883:         for (p = 0; p < 2; ++p) {
7884:           if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", coneNew[p], eStartNew, eMaxNew);
7885:         }
7886:         for (p = 2; p < 4; ++p) {
7887:           if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", coneNew[p], eMaxNew, eEndNew);
7888:         }
7889: #endif
7890:         supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], r);
7891:         supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], (r+1)%4);
7892:         DMPlexSetSupport(rdm, newp+r, supportNew);
7893: #if defined(PETSC_USE_DEBUG)
7894:         if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", newp+r, fMaxNew, fEndNew);
7895:         for (p = 0; p < 2; ++p) {
7896:           if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid cell [%D, %D)", supportNew[p], cMaxNew, cEndNew);
7897:         }
7898: #endif
7899:       }
7900:     }
7901:     /* Interior split edges have 2 vertices and the same faces as the parent */
7902:     DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
7903:     for (e = eStart; e < eMax; ++e) {
7904:       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);

7906:       for (r = 0; r < 2; ++r) {
7907:         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
7908:         const PetscInt *cone, *ornt, *support;
7909:         PetscInt        coneNew[2], coneSize, c, supportSize, s;

7911:         DMPlexGetCone(dm, e, &cone);
7912:         coneNew[0]       = vStartNew + (cone[0] - vStart);
7913:         coneNew[1]       = vStartNew + (cone[1] - vStart);
7914:         coneNew[(r+1)%2] = newv;
7915:         DMPlexSetCone(rdm, newp, coneNew);
7916: #if defined(PETSC_USE_DEBUG)
7917:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
7918:         for (p = 0; p < 2; ++p) {
7919:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
7920:         }
7921: #endif
7922:         DMPlexGetSupportSize(dm, e, &supportSize);
7923:         DMPlexGetSupport(dm, e, &support);
7924:         for (s = 0; s < supportSize; ++s) {
7925:           DMPlexGetConeSize(dm, support[s], &coneSize);
7926:           DMPlexGetCone(dm, support[s], &cone);
7927:           DMPlexGetConeOrientation(dm, support[s], &ornt);
7928:           for (c = 0; c < coneSize; ++c) {
7929:             if (cone[c] == e) break;
7930:           }
7931:           if (support[s] < fMax) {
7932:             supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%4;
7933:           } else {
7934:             supportRef[s] = fStartNew + (fMax       - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
7935:           }
7936:         }
7937:         DMPlexSetSupport(rdm, newp, supportRef);
7938: #if defined(PETSC_USE_DEBUG)
7939:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
7940:         for (p = 0; p < supportSize; ++p) {
7941:           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
7942:         }
7943: #endif
7944:       }
7945:     }
7946:     /* Interior face edges have 2 vertices and 2+cells faces */
7947:     for (f = fStart; f < fMax; ++f) {
7948:       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};
7949:       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
7950:       const PetscInt *cone, *coneCell, *orntCell, *support;
7951:       PetscInt        coneNew[2], coneSize, c, supportSize, s;

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

7957:         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
7958:         coneNew[1] = newv;
7959:         DMPlexSetCone(rdm, newp, coneNew);
7960: #if defined(PETSC_USE_DEBUG)
7961:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
7962:         for (p = 0; p < 2; ++p) {
7963:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
7964:         }
7965: #endif
7966:         DMPlexGetSupportSize(dm, f, &supportSize);
7967:         DMPlexGetSupport(dm, f, &support);
7968:         supportRef[0] = fStartNew + (f - fStart)*4 + r;
7969:         supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
7970:         for (s = 0; s < supportSize; ++s) {
7971:           DMPlexGetConeSize(dm, support[s], &coneSize);
7972:           DMPlexGetCone(dm, support[s], &coneCell);
7973:           DMPlexGetConeOrientation(dm, support[s], &orntCell);
7974:           for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
7975:           if (support[s] < cMax) {
7976:             supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
7977:           } else {
7978:             supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + r;
7979:           }
7980:         }
7981:         DMPlexSetSupport(rdm, newp, supportRef);
7982: #if defined(PETSC_USE_DEBUG)
7983:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
7984:         for (p = 0; p < 2+supportSize; ++p) {
7985:           if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportRef[p], fStartNew, fEndNew);
7986:         }
7987: #endif
7988:       }
7989:     }
7990:     /* Interior cell edges have 2 vertices and 4 faces */
7991:     for (c = cStart; c < cMax; ++c) {
7992:       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};
7993:       const PetscInt  newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
7994:       const PetscInt *cone;
7995:       PetscInt        coneNew[2], supportNew[4];

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

8001:         coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[r] - fStart);
8002:         coneNew[1] = newv;
8003:         DMPlexSetCone(rdm, newp, coneNew);
8004: #if defined(PETSC_USE_DEBUG)
8005:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
8006:         for (p = 0; p < 2; ++p) {
8007:           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
8008:         }
8009: #endif
8010:         for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
8011:         DMPlexSetSupport(rdm, newp, supportNew);
8012: #if defined(PETSC_USE_DEBUG)
8013:         if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not an edge [%D, %D)", newp, eStartNew, eMaxNew);
8014:         for (p = 0; p < 4; ++p) {
8015:           if ((supportNew[p] < fStartNew) || (supportNew[p] >= fMaxNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a face [%D, %D)", supportNew[p], fStartNew, fMaxNew);
8016:         }
8017: #endif
8018:       }
8019:     }
8020:     /* Hybrid edges have two vertices and the same faces */
8021:     for (e = eMax; e < eEnd; ++e) {
8022:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (e - eMax);
8023:       const PetscInt *cone, *support, *fcone;
8024:       PetscInt        coneNew[2], size, fsize, s;

8026:       DMPlexGetCone(dm, e, &cone);
8027:       DMPlexGetSupportSize(dm, e, &size);
8028:       DMPlexGetSupport(dm, e, &support);
8029:       coneNew[0] = vStartNew + (cone[0] - vStart);
8030:       coneNew[1] = vStartNew + (cone[1] - vStart);
8031:       DMPlexSetCone(rdm, newp, coneNew);
8032: #if defined(PETSC_USE_DEBUG)
8033:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
8034:       for (p = 0; p < 2; ++p) {
8035:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
8036:       }
8037: #endif
8038:       for (s = 0; s < size; ++s) {
8039:         DMPlexGetConeSize(dm, support[s], &fsize);
8040:         DMPlexGetCone(dm, support[s], &fcone);
8041:         for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
8042:         if ((c < 2) || (c > 3)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Edge %D not found in cone of face %D", e, support[s]);
8043:         supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + c-2;
8044:       }
8045:       DMPlexSetSupport(rdm, newp, supportRef);
8046: #if defined(PETSC_USE_DEBUG)
8047:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
8048:       for (p = 0; p < size; ++p) {
8049:         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", supportRef[p], fMaxNew, fEndNew);
8050:       }
8051: #endif
8052:     }
8053:     /* Hybrid face edges have 2 vertices and 2+cells faces */
8054:     for (f = fMax; f < fEnd; ++f) {
8055:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
8056:       const PetscInt *cone, *support, *ccone, *cornt;
8057:       PetscInt        coneNew[2], size, csize, s;

8059:       DMPlexGetCone(dm, f, &cone);
8060:       DMPlexGetSupportSize(dm, f, &size);
8061:       DMPlexGetSupport(dm, f, &support);
8062:       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
8063:       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
8064:       DMPlexSetCone(rdm, newp, coneNew);
8065: #if defined(PETSC_USE_DEBUG)
8066:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
8067:       for (p = 0; p < 2; ++p) {
8068:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
8069:       }
8070: #endif
8071:       supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 0;
8072:       supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 1;
8073:       for (s = 0; s < size; ++s) {
8074:         DMPlexGetConeSize(dm, support[s], &csize);
8075:         DMPlexGetCone(dm, support[s], &ccone);
8076:         DMPlexGetConeOrientation(dm, support[s], &cornt);
8077:         for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
8078:         if ((c < 2) || (c >= csize)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Hybrid face %D is not in cone of hybrid cell %D", f, support[s]);
8079:         supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + c-2;
8080:       }
8081:       DMPlexSetSupport(rdm, newp, supportRef);
8082: #if defined(PETSC_USE_DEBUG)
8083:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
8084:       for (p = 0; p < 2+size; ++p) {
8085:         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", supportRef[p], fMaxNew, fEndNew);
8086:       }
8087: #endif
8088:     }
8089:     /* Hybrid cell edges have 2 vertices and 4 faces */
8090:     for (c = cMax; c < cEnd; ++c) {
8091:       const PetscInt  newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
8092:       const PetscInt *cone, *support;
8093:       PetscInt        coneNew[2], size;

8095:       DMPlexGetCone(dm, c, &cone);
8096:       DMPlexGetSupportSize(dm, c, &size);
8097:       DMPlexGetSupport(dm, c, &support);
8098:       coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[0] - fStart);
8099:       coneNew[1] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[1] - fStart);
8100:       DMPlexSetCone(rdm, newp, coneNew);
8101: #if defined(PETSC_USE_DEBUG)
8102:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
8103:       for (p = 0; p < 2; ++p) {
8104:         if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", coneNew[p], vStartNew, vEndNew);
8105:       }
8106: #endif
8107:       supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 0;
8108:       supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 1;
8109:       supportRef[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 2;
8110:       supportRef[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 3;
8111:       DMPlexSetSupport(rdm, newp, supportRef);
8112: #if defined(PETSC_USE_DEBUG)
8113:       if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid edge [%D, %D)", newp, eMaxNew, eEndNew);
8114:       for (p = 0; p < 4; ++p) {
8115:         if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a hybrid face [%D, %D)", supportRef[p], fMaxNew, fEndNew);
8116:       }
8117: #endif
8118:     }
8119:     /* Interior vertices have identical supports */
8120:     for (v = vStart; v < vEnd; ++v) {
8121:       const PetscInt  newp = vStartNew + (v - vStart);
8122:       const PetscInt *support, *cone;
8123:       PetscInt        size, s;

8125:       DMPlexGetSupportSize(dm, v, &size);
8126:       DMPlexGetSupport(dm, v, &support);
8127:       for (s = 0; s < size; ++s) {
8128:         PetscInt r = 0;

8130:         DMPlexGetCone(dm, support[s], &cone);
8131:         if (cone[1] == v) r = 1;
8132:         if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
8133:         else