Actual source code: plexrefine.c

petsc-3.12.3 2020-01-03
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                   supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (support[s] - eMax);
8134:       }
8135:       DMPlexSetSupport(rdm, newp, supportRef);
8136: #if defined(PETSC_USE_DEBUG)
8137:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
8138:       for (p = 0; p < size; ++p) {
8139:         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);
8140:       }
8141: #endif
8142:     }
8143:     /* Interior edge vertices have 2 + faces supports */
8144:     for (e = eStart; e < eMax; ++e) {
8145:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
8146:       const PetscInt *cone, *support;
8147:       PetscInt        size, s;

8149:       DMPlexGetSupportSize(dm, e, &size);
8150:       DMPlexGetSupport(dm, e, &support);
8151:       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
8152:       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
8153:       for (s = 0; s < size; ++s) {
8154:         PetscInt r;

8156:         DMPlexGetCone(dm, support[s], &cone);
8157:         for (r = 0; r < 4; ++r) if (cone[r] == e) break;
8158:         if (support[s] < fMax) {
8159:           supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*4 + r;
8160:         } else {
8161:           supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (fMax       - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (support[s] - fMax);
8162:         }
8163:       }
8164:       DMPlexSetSupport(rdm, newp, supportRef);
8165: #if defined(PETSC_USE_DEBUG)
8166:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
8167:       for (p = 0; p < 2+size; ++p) {
8168:         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);
8169:       }
8170: #endif
8171:     }
8172:     /* Interior face vertices have 4 + cells supports */
8173:     for (f = fStart; f < fMax; ++f) {
8174:       const PetscInt  newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
8175:       const PetscInt *cone, *support;
8176:       PetscInt        size, s;

8178:       DMPlexGetSupportSize(dm, f, &size);
8179:       DMPlexGetSupport(dm, f, &support);
8180:       for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eMax - eStart)*2 +  (f - fStart)*4 + r;
8181:       for (s = 0; s < size; ++s) {
8182:         PetscInt r;

8184:         DMPlexGetCone(dm, support[s], &cone);
8185:         for (r = 0; r < 6; ++r) if (cone[r] == f) break;
8186:         if (support[s] < cMax) {
8187:           supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (support[s] - cStart)*6 + r;
8188:         } else {
8189:           supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax       - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (support[s] - cMax);
8190:         }
8191:       }
8192:       DMPlexSetSupport(rdm, newp, supportRef);
8193: #if defined(PETSC_USE_DEBUG)
8194:       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a vertex [%D, %D)", newp, vStartNew, vEndNew);
8195:       for (p = 0; p < 4+size; ++p) {
8196:         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);
8197:       }
8198: #endif
8199:     }
8200:     /* Cell vertices have 6 supports */
8201:     for (c = cStart; c < cMax; ++c) {
8202:       const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
8203:       PetscInt       supportNew[6];

8205:       for (r = 0; r < 6; ++r) {
8206:         supportNew[r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
8207:       }
8208:       DMPlexSetSupport(rdm, newp, supportNew);
8209:     }
8210:     PetscFree(supportRef);
8211:     break;
8212:   default:
8213:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
8214:   }
8215:   return(0);
8216: }

8218: static PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
8219: {
8220:   PetscSection          coordSection, coordSectionNew;
8221:   Vec                   coordinates, coordinatesNew;
8222:   PetscScalar          *coords, *coordsNew;
8223:   const PetscInt        numVertices = depthSize ? depthSize[0] : 0;
8224:   PetscInt              dim, spaceDim, depth, bs, coordSizeNew, cStart, cEnd, cMax;
8225:   PetscInt              c, vStart, vStartNew, vEnd, v, eStart, eEnd, eMax, e, fStart, fEnd, fMax, f;
8226:   PetscInt              cStartNew, cEndNew, vEndNew, *parentId = NULL;
8227:   VecType               vtype;
8228:   PetscBool             isperiodic, localize = PETSC_FALSE, needcoords = PETSC_FALSE;
8229:   const PetscReal      *maxCell, *L;
8230:   const DMBoundaryType *bd;
8231:   PetscErrorCode        ierr;

8234:   DMGetDimension(dm, &dim);
8235:   DMPlexGetDepth(dm, &depth);
8236:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
8237:   DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
8238:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
8239:   DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
8240:   DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, NULL);
8241:   if (cMax < 0) cMax = cEnd;
8242:   if (fMax < 0) fMax = fEnd;
8243:   if (eMax < 0) eMax = eEnd;
8244:   GetDepthStart_Private(depth, depthSize, &cStartNew, NULL, NULL, &vStartNew);
8245:   GetDepthEnd_Private(depth, depthSize, &cEndNew, NULL, NULL, &vEndNew);
8246:   DMGetPeriodicity(dm, &isperiodic, &maxCell, &L, &bd);
8247:   /* Determine if we need to localize coordinates when generating them */
8248:   if (isperiodic && !maxCell) {
8249:     DMGetCoordinatesLocalized(dm, &localize);
8250:     if (!localize) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot refine if coordinates have not been localized");
8251:   }
8252:   if (isperiodic) {
8253:     PetscOptionsBegin(PetscObjectComm((PetscObject)dm),((PetscObject)dm)->prefix,"DMPlex coords refinement options","DM");
8254:     PetscOptionsBool("-dm_plex_refine_localize","Automatically localize from parent cells",NULL,localize,&localize,NULL);
8255:     PetscOptionsEnd();
8256:     if (localize) {
8257:       DMLocalizeCoordinates(dm);
8258:     }
8259:   }
8260:   DMSetPeriodicity(rdm, isperiodic,  maxCell,  L,  bd);

8262:   DMGetCoordinateSection(dm, &coordSection);
8263:   PetscSectionGetFieldComponents(coordSection, 0, &spaceDim);
8264:   PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);
8265:   PetscSectionSetNumFields(coordSectionNew, 1);
8266:   PetscSectionSetFieldComponents(coordSectionNew, 0, spaceDim);

8268:   if (localize) {
8269:     PetscInt p, r, newp, *pi;

8271:     /* New coordinates will be already localized on the cell */
8272:     PetscSectionSetChart(coordSectionNew, 0, vStartNew+numVertices);

8274:     /* We need the parentId to properly localize coordinates */
8275:     PetscMalloc1(cEndNew-cStartNew,&pi);
8276:     switch (refiner) {
8277:     case REFINER_NOOP:
8278:       break;
8279:     case REFINER_SIMPLEX_1D:
8280:       for (p = cStart; p < cEnd; ++p) {
8281:         for (r = 0; r < 2; ++r) {
8282:           newp     = (p - cStart)*2 + r;
8283:           pi[newp] = p;
8284:         }
8285:       }
8286:       break;
8287:     case REFINER_SIMPLEX_2D:
8288:       for (p = cStart; p < cEnd; ++p) {
8289:         for (r = 0; r < 4; ++r) {
8290:           newp     = (p - cStart)*4 + r;
8291:           pi[newp] = p;
8292:         }
8293:       }
8294:       break;
8295:     case REFINER_HEX_2D:
8296:       for (p = cStart; p < cEnd; ++p) {
8297:         for (r = 0; r < 4; ++r) {
8298:           newp     = (p - cStart)*4 + r;
8299:           pi[newp] = p;
8300:         }
8301:       }
8302:       break;
8303:     case REFINER_SIMPLEX_TO_HEX_2D:
8304:       for (p = cStart; p < cEnd; ++p) {
8305:         for (r = 0; r < 3; ++r) {
8306:           newp     = (p - cStart)*3 + r;
8307:           pi[newp] = p;
8308:         }
8309:       }
8310:       break;
8311:     case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
8312:       for (p = cStart; p < cMax; ++p) {
8313:         for (r = 0; r < 3; ++r) {
8314:           newp     = (p - cStart)*3 + r;
8315:           pi[newp] = p;
8316:         }
8317:       }
8318:       for (p = cMax; p < cEnd; ++p) {
8319:         for (r = 0; r < 4; ++r) {
8320:           newp     = (cMax - cStart)*3 + (p - cMax)*4 + r;
8321:           pi[newp] = p;
8322:         }
8323:       }
8324:       /* The refiner needs midpoint vertices on hybrid edges and hybrid cells */
8325:       cMax = cEnd;
8326:       eMax = eEnd;
8327:       break;
8328:     case REFINER_HYBRID_SIMPLEX_2D:
8329:       for (p = cStart; p < cMax; ++p) {
8330:         for (r = 0; r < 4; ++r) {
8331:           newp     = (p - cStart)*4 + r;
8332:           pi[newp] = p;
8333:         }
8334:       }
8335:       for (p = cMax; p < cEnd; ++p) {
8336:         for (r = 0; r < 2; ++r) {
8337:           newp     = (cMax - cStart)*4 + (p - cMax)*2 + r;
8338:           pi[newp] = p;
8339:         }
8340:       }
8341:       break;
8342:     case REFINER_HYBRID_HEX_2D:
8343:       for (p = cStart; p < cMax; ++p) {
8344:         for (r = 0; r < 4; ++r) {
8345:           newp     = (p - cStart)*4 + r;
8346:           pi[newp] = p;
8347:         }
8348:       }
8349:       for (p = cMax; p < cEnd; ++p) {
8350:         for (r = 0; r < 2; ++r) {
8351:           newp     = (cMax - cStart)*4 + (p - cMax)*2 + r;
8352:           pi[newp] = p;
8353:         }
8354:       }
8355:       break;
8356:     case REFINER_SIMPLEX_3D:
8357:       for (p = cStart; p < cEnd; ++p) {
8358:         for (r = 0; r < 8; ++r) {
8359:           newp     = (p - cStart)*8 + r;
8360:           pi[newp] = p;
8361:         }
8362:       }
8363:       break;
8364:     case REFINER_HYBRID_SIMPLEX_3D:
8365:       for (p = cStart; p < cMax; ++p) {
8366:         for (r = 0; r < 8; ++r) {
8367:           newp     = (p - cStart)*8 + r;
8368:           pi[newp] = p;
8369:         }
8370:       }
8371:       for (p = cMax; p < cEnd; ++p) {
8372:         for (r = 0; r < 4; ++r) {
8373:           newp     = (cMax - cStart)*8 + (p - cMax)*4 + r;
8374:           pi[newp] = p;
8375:         }
8376:       }
8377:       break;
8378:     case REFINER_SIMPLEX_TO_HEX_3D:
8379:       for (p = cStart; p < cEnd; ++p) {
8380:         for (r = 0; r < 4; ++r) {
8381:           newp     = (p - cStart)*4 + r;
8382:           pi[newp] = p;
8383:         }
8384:       }
8385:       break;
8386:     case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
8387:       for (p = cStart; p < cMax; ++p) {
8388:         for (r = 0; r < 4; ++r) {
8389:           newp     = (p - cStart)*4 + r;
8390:           pi[newp] = p;
8391:         }
8392:       }
8393:       for (p = cMax; p < cEnd; ++p) {
8394:         for (r = 0; r < 3; ++r) {
8395:           newp     = (cMax - cStart)*4 + (p - cMax)*3 + r;
8396:           pi[newp] = p;
8397:         }
8398:       }
8399:       break;
8400:     case REFINER_HEX_3D:
8401:       for (p = cStart; p < cEnd; ++p) {
8402:         for (r = 0; r < 8; ++r) {
8403:           newp = (p - cStart)*8 + r;
8404:           pi[newp] = p;
8405:         }
8406:       }
8407:       break;
8408:     case REFINER_HYBRID_HEX_3D:
8409:       for (p = cStart; p < cMax; ++p) {
8410:         for (r = 0; r < 8; ++r) {
8411:           newp = (p - cStart)*8 + r;
8412:           pi[newp] = p;
8413:         }
8414:       }
8415:       for (p = cMax; p < cEnd; ++p) {
8416:         for (r = 0; r < 4; ++r) {
8417:           newp = (cMax - cStart)*8 + (p - cMax)*4 + r;
8418:           pi[newp] = p;
8419:         }
8420:       }
8421:       break;
8422:     default:
8423:       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
8424:     }
8425:     parentId = pi;
8426:   } else {
8427:     /* The refiner needs midpoint vertices on hybrid edges and hybrid cells */
8428:     if (REFINER_HYBRID_SIMPLEX_TO_HEX_2D == refiner) { cMax = cEnd; eMax = eEnd; }
8429:     PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+numVertices);
8430:   }

8432:   /* All vertices have the spaceDim coordinates */
8433:   if (localize) {
8434:     PetscInt c;

8436:     for (c = cStartNew; c < cEndNew; ++c) {
8437:       PetscInt *cone = NULL;
8438:       PetscInt  closureSize, coneSize = 0, p, pdof;

8440:       PetscSectionGetDof(coordSection, parentId[c], &pdof);
8441:       if (pdof) { /* localize on all cells that are refinement of a localized parent cell */
8442:         DMPlexGetTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);
8443:         for (p = 0; p < closureSize*2; p += 2) {
8444:           const PetscInt point = cone[p];
8445:           if ((point >= vStartNew) && (point < vEndNew)) coneSize++;
8446:         }
8447:         DMPlexRestoreTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);
8448:         PetscSectionSetDof(coordSectionNew, c, coneSize*spaceDim);
8449:         PetscSectionSetFieldDof(coordSectionNew, c, 0, coneSize*spaceDim);
8450:       }
8451:     }
8452:   }
8453:   for (v = vStartNew; v < vStartNew+numVertices; ++v) {
8454:     PetscSectionSetDof(coordSectionNew, v, spaceDim);
8455:     PetscSectionSetFieldDof(coordSectionNew, v, 0, spaceDim);
8456:   }
8457:   PetscSectionSetUp(coordSectionNew);
8458:   DMSetCoordinateSection(rdm, PETSC_DETERMINE, coordSectionNew);
8459:   DMGetCoordinatesLocal(dm, &coordinates);
8460:   PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);
8461:   VecCreate(PETSC_COMM_SELF, &coordinatesNew);
8462:   PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");
8463:   VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);
8464:   VecGetBlockSize(coordinates, &bs);
8465:   VecSetBlockSize(coordinatesNew, bs);
8466:   VecGetType(coordinates, &vtype);
8467:   VecSetType(coordinatesNew, vtype);
8468:   VecGetArray(coordinates, &coords);
8469:   VecGetArray(coordinatesNew, &coordsNew);

8471:   switch (refiner) {
8472:   case REFINER_NOOP: break;
8473:   case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
8474:   case REFINER_SIMPLEX_TO_HEX_3D:
8475:   case REFINER_HEX_3D:
8476:   case REFINER_HYBRID_HEX_3D:
8477:     /* Face vertices have the average of corner coordinates */
8478:     for (f = fStart; f < fMax; ++f) {
8479:       const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
8480:       PetscInt      *cone = NULL;
8481:       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;

8483:       DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);
8484:       for (p = 0; p < closureSize*2; p += 2) {
8485:         const PetscInt point = cone[p];
8486:         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
8487:       }
8488:       if (localize) {
8489:         const PetscInt *support = NULL;
8490:         PetscInt       *rStar = NULL;
8491:         PetscInt        supportSize, rStarSize, coff, s, ccoff[8];
8492:         PetscBool       cellfound = PETSC_FALSE;

8494:         DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
8495:         DMPlexGetSupportSize(dm,f,&supportSize);
8496:         DMPlexGetSupport(dm,f,&support);
8497:         /* Compute average of coordinates for each cell sharing the face */
8498:         for (s = 0; s < supportSize; ++s) {
8499:           PetscScalar     coordsNewAux[3] = { 0.0, 0.0, 0.0 };
8500:           PetscInt       *cellCone = NULL;
8501:           PetscInt        cellClosureSize, cellConeSize = 0, cdof;
8502:           const PetscInt  cell = support[s];
8503:           PetscBool       copyoff = PETSC_FALSE;

8505:           DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);
8506:           for (p = 0; p < cellClosureSize*2; p += 2) {
8507:             const PetscInt point = cellCone[p];
8508:             if ((point >= vStart) && (point < vEnd)) cellCone[cellConeSize++] = point;
8509:           }
8510:           PetscSectionGetDof(coordSection, cell, &cdof);
8511:           if (!cdof) { /* the parent cell does not have localized coordinates */
8512:             cellfound = PETSC_TRUE;
8513:             for (v = 0; v < coneSize; ++v) {
8514:               PetscSectionGetOffset(coordSection, cone[v], &off[v]);
8515:               for (d = 0; d < spaceDim; ++d) coordsNewAux[d] += coords[off[v]+d];
8516:             }
8517:             for (d = 0; d < spaceDim; ++d) coordsNewAux[d] /= coneSize;
8518:           } else {
8519:             PetscSectionGetOffset(coordSection, cell, &coff);
8520:             for (p = 0; p < coneSize; ++p) {
8521:               const PetscInt tv = cone[p];
8522:               PetscInt       cv, voff;
8523:               PetscBool      locv = PETSC_TRUE;

8525:               for (cv = 0; cv < cellConeSize; ++cv) {
8526:                 if (cellCone[cv] == tv) {
8527:                   ccoff[p] = spaceDim*cv + coff;
8528:                   break;
8529:                 }
8530:               }
8531:               if (cv == cellConeSize) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map vertex %D",tv);

8533:               PetscSectionGetOffset(coordSection, cone[p], &voff);
8534:               for (d = 0; d < spaceDim; ++d) {
8535:                 coordsNewAux[d] += coords[ccoff[p]+d];
8536:                 if (!cellfound && coords[voff+d] != coords[ccoff[p]+d]) locv = PETSC_FALSE;
8537:               }
8538:               if (locv && !cellfound) {
8539:                 cellfound = PETSC_TRUE;
8540:                 copyoff   = PETSC_TRUE;
8541:               }
8542:             }
8543:             for (d = 0; d < spaceDim; ++d) coordsNewAux[d] /= coneSize;

8545:             /* Found a valid face for the "vertex" part of the Section (physical space)
8546:                i.e., a face that has at least one corner in the physical space */
8547:             if (copyoff) for (p = 0; p < coneSize; ++p) off[p] = ccoff[p];
8548:           }

8550:           /* Localize new coordinates on each refined cell */
8551:           for (v = 0; v < rStarSize*2; v += 2) {
8552:             if ((rStar[v] >= cStartNew) && (rStar[v] < cEndNew) && parentId[rStar[v]-cStartNew] == cell) {
8553:               PetscInt       *rcone = NULL, rclosureSize, lid, rcdof, rcoff;
8554:               const PetscInt  rcell = rStar[v];

8556:               PetscSectionGetDof(coordSectionNew, rcell, &rcdof);
8557:               if (!rcdof) continue;
8558:               PetscSectionGetOffset(coordSectionNew, rcell, &rcoff);
8559:               DMPlexGetTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);
8560:               for (p = 0, lid = 0; p < rclosureSize*2; p += 2) {
8561:                 if (rcone[p] == newv) {
8562:                   for (d = 0; d < spaceDim; d++) coordsNew[rcoff + lid*spaceDim + d] = coordsNewAux[d];
8563:                   break;
8564:                 }
8565:                 if (rcone[p] >= vStartNew && rcone[p] < vEndNew) lid++;
8566:               }
8567:               DMPlexRestoreTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);
8568:               if (p == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D",newv);
8569:             }
8570:           }
8571:           DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);
8572:         }
8573:         DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
8574:         if (!cellfound) {
8575:           /* Could not find a valid face for the vertex part, we will get this vertex later (final reduction) */
8576:           needcoords = PETSC_TRUE;
8577:           coneSize   = 0;
8578:         }
8579:       } else {
8580:         for (v = 0; v < coneSize; ++v) {
8581:           PetscSectionGetOffset(coordSection, cone[v], &off[v]);
8582:         }
8583:       }
8584:       PetscSectionGetOffset(coordSectionNew, newv, &offnew);
8585:       if (coneSize) {
8586:         for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = 0.0;
8587:         for (v = 0; v < coneSize; ++v) {DMLocalizeAddCoordinate_Internal(dm, spaceDim, &coords[off[0]], &coords[off[v]], &coordsNew[offnew]);}
8588:         for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] /= coneSize;
8589:       } else {
8590:         for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = PETSC_MIN_REAL;
8591:       }
8592:       DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);
8593:     }
8594:   case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
8595:   case REFINER_SIMPLEX_TO_HEX_2D:
8596:   case REFINER_HEX_2D:
8597:   case REFINER_HYBRID_HEX_2D:
8598:   case REFINER_SIMPLEX_1D:
8599:     /* Cell vertices have the average of corner coordinates */
8600:     for (c = cStart; c < cMax; ++c) {
8601:       const PetscInt newv = vStartNew + (vEnd - vStart) + (dim > 1 ? (eMax - eStart) : 0) + (c - cStart) + (dim > 2 ? (fMax - fStart) : 0);
8602:       PetscInt      *cone = NULL;
8603:       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d, cdof = 0;

8605:       DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);
8606:       for (p = 0; p < closureSize*2; p += 2) {
8607:         const PetscInt point = cone[p];
8608:         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
8609:       }
8610:       if (localize) {
8611:         PetscSectionGetDof(coordSection, c, &cdof);
8612:       }
8613:       if (cdof) {
8614:         PetscInt coff;

8616:         PetscSectionGetOffset(coordSection, c, &coff);
8617:         for (v = 0; v < coneSize; ++v) off[v] = spaceDim*v + coff;
8618:       } else {
8619:         for (v = 0; v < coneSize; ++v) {
8620:           PetscSectionGetOffset(coordSection, cone[v], &off[v]);
8621:         }
8622:       }
8623:       PetscSectionGetOffset(coordSectionNew, newv, &offnew);
8624:       for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = 0.0;
8625:       for (v = 0; v < coneSize; ++v) {DMLocalizeAddCoordinate_Internal(dm, spaceDim, &coords[off[0]], &coords[off[v]], &coordsNew[offnew]);}
8626:       for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] /= coneSize;
8627:       DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);

8629:       /* Localize new coordinates on each refined cell */
8630:       if (cdof) {
8631:         PetscInt *rStar = NULL, rStarSize;

8633:         DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
8634:         for (v = 0; v < rStarSize*2; v += 2) {
8635:           if ((rStar[v] >= cStartNew) && (rStar[v] < cEndNew)) {
8636:             PetscInt *cone = NULL, closureSize, lid, coff, rc, rcdof;

8638:             rc   = rStar[v];
8639:             PetscSectionGetDof(coordSectionNew, rc, &rcdof);
8640:             if (!rcdof) continue;
8641:             PetscSectionGetOffset(coordSectionNew, rc, &coff);
8642:             DMPlexGetTransitiveClosure(rdm, rc, PETSC_TRUE, &closureSize, &cone);
8643:             for (p = 0, lid = 0; p < closureSize*2; p += 2) {
8644:               if (cone[p] == newv) {
8645:                 for (d = 0; d < spaceDim; d++) coordsNew[coff + lid*spaceDim + d] = coordsNew[offnew + d];
8646:                 break;
8647:               }
8648:               if (cone[p] >= vStartNew && cone[p] < vEndNew) lid++;
8649:             }
8650:             if (p == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D",newv);
8651:             DMPlexRestoreTransitiveClosure(rdm, rc, PETSC_TRUE, &closureSize, &cone);
8652:           }
8653:         }
8654:         DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
8655:       }
8656:     }
8657:   case REFINER_SIMPLEX_2D:
8658:   case REFINER_HYBRID_SIMPLEX_2D:
8659:   case REFINER_SIMPLEX_3D:
8660:   case REFINER_HYBRID_SIMPLEX_3D:
8661:     /* Edge vertices have the average of endpoint coordinates */
8662:     for (e = eStart; e < eMax; ++e) {
8663:       const PetscInt  newv = vStartNew + (vEnd - vStart) + (e - eStart);
8664:       const PetscInt *cone;
8665:       PetscInt        coneSize, offA, offB, offnew, d;

8667:       DMPlexGetConeSize(dm, e, &coneSize);
8668:       if (coneSize != 2) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize);
8669:       DMPlexGetCone(dm, e, &cone);
8670:       if (localize) {
8671:         PetscInt   coff, toffA = -1, toffB = -1, voffA, voffB;
8672:         PetscInt  *eStar = NULL, eStarSize;
8673:         PetscInt  *rStar = NULL, rStarSize;
8674:         PetscBool  cellfound = PETSC_FALSE;

8676:         offA = offB = -1;
8677:         PetscSectionGetOffset(coordSection, cone[0], &voffA);
8678:         PetscSectionGetOffset(coordSection, cone[1], &voffB);
8679:         DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &eStarSize, &eStar);
8680:         DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
8681:         for (v = 0; v < eStarSize*2; v += 2) {
8682:           if ((eStar[v] >= cStart) && (eStar[v] < cEnd)) {
8683:             PetscScalar     coordsNewAux[3] = {0., 0., 0.};
8684:             PetscInt       *cellCone = NULL;
8685:             PetscInt        cellClosureSize, s, cv, cdof;
8686:             PetscBool       locvA = PETSC_TRUE, locvB = PETSC_TRUE;
8687:             const PetscInt  cell = eStar[v];

8689:             PetscSectionGetDof(coordSection, cell, &cdof);
8690:             if (!cdof) {
8691:               /* Found a valid edge for the "vertex" part of the Section */
8692:               offA = voffA;
8693:               offB = voffB;
8694:               cellfound = PETSC_TRUE;
8695:             } else {
8696:               PetscSectionGetOffset(coordSection, cell, &coff);
8697:               DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);
8698:               for (s = 0, cv = 0; s < cellClosureSize*2; s += 2) {
8699:                 const PetscInt point = cellCone[s];
8700:                 if ((point >= vStart) && (point < vEnd)) {
8701:                   if (point == cone[0]) toffA = spaceDim*cv + coff;
8702:                   else if (point == cone[1]) toffB = spaceDim*cv + coff;
8703:                   cv++;
8704:                 }
8705:               }
8706:               DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);
8707:               for (d = 0; d < spaceDim; ++d) {
8708:                 coordsNewAux[d] = 0.5*(coords[toffA+d] + coords[toffB+d]);
8709:                 if (coords[toffA+d] != coords[voffA+d]) locvA = PETSC_FALSE;
8710:                 if (coords[toffB+d] != coords[voffB+d]) locvB = PETSC_FALSE;
8711:               }
8712:               /* Found a valid edge for the "vertex" part of the Section */
8713:               if (!cellfound && (locvA || locvB)) {
8714:                 cellfound = PETSC_TRUE;
8715:                 offA = toffA;
8716:                 offB = toffB;
8717:               }
8718:             }

8720:             /* Localize new coordinates on each refined cell */
8721:             for (s = 0; s < rStarSize*2; s += 2) {
8722:               if ((rStar[s] >= cStartNew) && (rStar[s] < cEndNew) && parentId[rStar[s]-cStartNew] == cell) {
8723:                 PetscInt       *rcone = NULL, rclosureSize, lid, p, rcdof;
8724:                 const PetscInt  rcell = rStar[s];

8726:                 PetscSectionGetDof(coordSectionNew, rcell, &rcdof);
8727:                 if (!rcdof) continue;
8728:                 PetscSectionGetOffset(coordSectionNew, rcell, &coff);
8729:                 DMPlexGetTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);
8730:                 for (p = 0, lid = 0; p < rclosureSize*2; p += 2) {
8731:                   if (rcone[p] == newv) {
8732:                     for (d = 0; d < spaceDim; d++) coordsNew[coff + lid*spaceDim + d] = coordsNewAux[d];
8733:                     break;
8734:                   }
8735:                   if (rcone[p] >= vStartNew && rcone[p] < vEndNew) lid++;
8736:                 }
8737:                 DMPlexRestoreTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);
8738:                 if (p == rclosureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D",newv);
8739:               }
8740:             }
8741:           }
8742:         }
8743:         DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &eStarSize, &eStar);
8744:         DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
8745:         if (!cellfound) {
8746:           /* Could not find a valid edge for the vertex part, we will get this vertex later (final reduction) */
8747:           needcoords = PETSC_TRUE;
8748:         }
8749:       } else {
8750:         PetscSectionGetOffset(coordSection, cone[0], &offA);
8751:         PetscSectionGetOffset(coordSection, cone[1], &offB);
8752:       }
8753:       PetscSectionGetOffset(coordSectionNew, newv, &offnew);
8754:       if (offA != -1 && offB != -1) {
8755:         DMLocalizeCoordinate_Internal(dm, spaceDim, &coords[offA], &coords[offB], &coordsNew[offnew]);
8756:         for (d = 0; d < spaceDim; ++d) {
8757:           coordsNew[offnew+d] = 0.5*(coords[offA+d] + coordsNew[offnew+d]);
8758:         }
8759:       } else {
8760:         for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = PETSC_MIN_REAL;
8761:       }
8762:     }
8763:     /* Old vertices have the same coordinates */
8764:     for (v = vStart; v < vEnd; ++v) {
8765:       const PetscInt newv = vStartNew + (v - vStart);
8766:       PetscInt       off, offnew, d;

8768:       PetscSectionGetOffset(coordSection, v, &off);
8769:       PetscSectionGetOffset(coordSectionNew, newv, &offnew);
8770:       for (d = 0; d < spaceDim; ++d) {
8771:         coordsNew[offnew+d] = coords[off+d];
8772:       }

8774:       /* Localize new coordinates on each refined cell */
8775:       if (localize) {
8776:         PetscInt  p;
8777:         PetscInt *rStar = NULL, rStarSize;

8779:         DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
8780:         for (p = 0; p < rStarSize*2; p += 2) {
8781:           if ((rStar[p] >= cStartNew) && (rStar[p] < cEndNew)) {
8782:             PetscScalar  ocoords[3] = {0,0,0}; /* dummy values for compiler warnings about uninitialized values */
8783:             PetscInt    *cone = NULL, closureSize, lid, coff, s, oc, cdof;

8785:             c    = rStar[p];
8786:             oc   = parentId[c-cStartNew];
8787:             PetscSectionGetDof(coordSectionNew, c, &cdof);
8788:             if (!cdof) continue;
8789:             PetscSectionGetDof(coordSection, oc, &cdof);
8790:             if (!cdof) continue;
8791:             PetscSectionGetOffset(coordSection, oc, &coff);
8792:             DMPlexGetTransitiveClosure(dm, oc, PETSC_TRUE, &closureSize, &cone);
8793:             for (s = 0, lid = 0; s < closureSize*2; s += 2) {
8794:               if (cone[s] == v) {
8795:                 for (d = 0; d < spaceDim; d++) ocoords[d] = coords[coff + lid*spaceDim + d];
8796:                 break;
8797:               }
8798:               if (cone[s] >= vStart && cone[s] < vEnd) lid++;
8799:             }
8800:             if (s == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map old vertex %D",v);
8801:             DMPlexRestoreTransitiveClosure(dm, oc, PETSC_TRUE, &closureSize, &cone);

8803:             PetscSectionGetOffset(coordSectionNew, c, &coff);
8804:             DMPlexGetTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);
8805:             for (s = 0, lid = 0; s < closureSize*2; s += 2) {
8806:               if (cone[s] == newv) {
8807:                 for (d = 0; d < spaceDim; d++) coordsNew[coff + lid*spaceDim + d] = ocoords[d];
8808:                 break;
8809:               }
8810:               if (cone[s] >= vStartNew && cone[s] < vEndNew) lid++;
8811:             }
8812:             if (s == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D",newv);
8813:             DMPlexRestoreTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);
8814:           }
8815:         }
8816:         DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
8817:       }
8818:     }
8819:     break;
8820:   default:
8821:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
8822:   }
8823:   VecRestoreArray(coordinates, &coords);
8824:   VecRestoreArray(coordinatesNew, &coordsNew);
8825:   DMSetCoordinatesLocal(rdm, coordinatesNew);

8827:   /* Final reduction (if needed) if we are localizing */
8828:   if (localize) {
8829:     PetscBool gred;

8831:     MPIU_Allreduce(&needcoords, &gred, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)rdm));
8832:     if (gred) {
8833:       DM                 cdm;
8834:       Vec                aux;
8835:       PetscSF            sf;
8836:       const PetscScalar *lArray;
8837:       PetscScalar       *gArray;
8838: #if defined(PETSC_USE_COMPLEX)
8839:       PetscInt          i, ln, gn;
8840:       PetscReal         *lrArray;
8841:       PetscReal         *grArray;
8842: #endif

8844:       DMGetCoordinateDM(rdm, &cdm);
8845:       DMCreateGlobalVector(cdm, &aux);
8846:       DMGetSectionSF(cdm, &sf);
8847:       VecGetArrayRead(coordinatesNew, &lArray);
8848:       VecSet(aux, PETSC_MIN_REAL);
8849:       VecGetArray(aux, &gArray);
8850: #if defined(PETSC_USE_COMPLEX)
8851:       VecGetLocalSize(aux, &gn);
8852:       VecGetLocalSize(coordinatesNew, &ln);
8853:       PetscMalloc2(ln,&lrArray,gn,&grArray);
8854:       for (i=0;i<ln;i++) lrArray[i] = PetscRealPart(lArray[i]);
8855:       for (i=0;i<gn;i++) grArray[i] = PetscRealPart(gArray[i]);
8856:       PetscSFReduceBegin(sf, MPIU_REAL, lrArray, grArray, MPIU_MAX);
8857:       PetscSFReduceEnd(sf, MPIU_REAL, lrArray, grArray, MPIU_MAX);
8858:       for (i=0;i<gn;i++) gArray[i] = grArray[i];
8859:       PetscFree2(lrArray,grArray);
8860: #else
8861:       PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_MAX);
8862:       PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_MAX);
8863: #endif
8864:       VecRestoreArrayRead(coordinatesNew, &lArray);
8865:       VecRestoreArray(aux, &gArray);
8866:       DMGlobalToLocalBegin(cdm, aux, INSERT_VALUES, coordinatesNew);
8867:       DMGlobalToLocalEnd(cdm, aux, INSERT_VALUES, coordinatesNew);
8868:       VecDestroy(&aux);
8869:     }
8870:   }
8871:   VecDestroy(&coordinatesNew);
8872:   PetscSectionDestroy(&coordSectionNew);
8873:   PetscFree(parentId);
8874:   return(0);
8875: }

8877: /*@
8878:   DMPlexCreateProcessSF - Create an SF which just has process connectivity

8880:   Collective on dm

8882:   Input Parameters:
8883: + dm      - The DM
8884: - sfPoint - The PetscSF which encodes point connectivity

8886:   Output Parameters:
8887: + processRanks - A list of process neighbors, or NULL
8888: - sfProcess    - An SF encoding the process connectivity, or NULL

8890:   Level: developer

8892: .seealso: PetscSFCreate(), DMPlexCreateTwoSidedProcessSF()
8893: @*/
8894: PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
8895: {
8896:   PetscInt           numRoots, numLeaves, l;
8897:   const PetscInt    *localPoints;
8898:   const PetscSFNode *remotePoints;
8899:   PetscInt          *localPointsNew;
8900:   PetscSFNode       *remotePointsNew;
8901:   PetscInt          *ranks, *ranksNew;
8902:   PetscMPIInt        size;
8903:   PetscErrorCode     ierr;

8910:   MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);
8911:   PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);
8912:   PetscMalloc1(numLeaves, &ranks);
8913:   for (l = 0; l < numLeaves; ++l) {
8914:     ranks[l] = remotePoints[l].rank;
8915:   }
8916:   PetscSortRemoveDupsInt(&numLeaves, ranks);
8917:   PetscMalloc1(numLeaves, &ranksNew);
8918:   PetscMalloc1(numLeaves, &localPointsNew);
8919:   PetscMalloc1(numLeaves, &remotePointsNew);
8920:   for (l = 0; l < numLeaves; ++l) {
8921:     ranksNew[l]              = ranks[l];
8922:     localPointsNew[l]        = l;
8923:     remotePointsNew[l].index = 0;
8924:     remotePointsNew[l].rank  = ranksNew[l];
8925:   }
8926:   PetscFree(ranks);
8927:   if (processRanks) {ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);}
8928:   else              {PetscFree(ranksNew);}
8929:   if (sfProcess) {
8930:     PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);
8931:     PetscObjectSetName((PetscObject) *sfProcess, "Process SF");
8932:     PetscSFSetFromOptions(*sfProcess);
8933:     PetscSFSetGraph(*sfProcess, size, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);
8934:   }
8935:   return(0);
8936: }

8938: static PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
8939: {
8940:   PetscSF            sf, sfNew, sfProcess;
8941:   IS                 processRanks;
8942:   MPI_Datatype       depthType;
8943:   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
8944:   const PetscInt    *localPoints, *neighbors;
8945:   const PetscSFNode *remotePoints;
8946:   PetscInt          *localPointsNew;
8947:   PetscSFNode       *remotePointsNew;
8948:   PetscInt          *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
8949:   PetscInt           ldepth, depth, numNeighbors, pStartNew, pEndNew, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r, n;
8950:   PetscInt           cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
8951:   PetscErrorCode     ierr;

8954:   DMPlexGetChart(rdm, &pStartNew, &pEndNew);
8955:   DMPlexGetDepth(dm, &ldepth);
8956:   MPIU_Allreduce(&ldepth, &depth, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));
8957:   if ((ldepth >= 0) && (depth != ldepth)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %D != %D", ldepth, depth);
8958:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
8959:   DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
8960:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
8961:   DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
8962:   DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
8963:   cMax = cMax < 0 ? cEnd : cMax;
8964:   fMax = fMax < 0 ? fEnd : fMax;
8965:   eMax = eMax < 0 ? eEnd : eMax;
8966:   if (refiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
8967:   DMGetPointSF(dm, &sf);
8968:   DMGetPointSF(rdm, &sfNew);
8969:   /* Calculate size of new SF */
8970:   PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);
8971:   if (numRoots < 0) return(0);
8972:   for (l = 0; l < numLeaves; ++l) {
8973:     const PetscInt p = localPoints[l];

8975:     switch (refiner) {
8976:     case REFINER_SIMPLEX_1D:
8977:       if ((p >= vStart) && (p < vEnd)) {
8978:         /* Interior vertices stay the same */
8979:         ++numLeavesNew;
8980:       } else if ((p >= cStart && p < cMax)) {
8981:         /* Interior cells add new cells and interior vertices */
8982:         numLeavesNew += 2 + 1;
8983:       }
8984:       break;
8985:     case REFINER_SIMPLEX_2D:
8986:     case REFINER_HYBRID_SIMPLEX_2D:
8987:       if ((p >= vStart) && (p < vEnd)) {
8988:         /* Interior vertices stay the same */
8989:         ++numLeavesNew;
8990:       } else if ((p >= fStart) && (p < fMax)) {
8991:         /* Interior faces add new faces and vertex */
8992:         numLeavesNew += 2 + 1;
8993:       } else if ((p >= fMax) && (p < fEnd)) {
8994:         /* Hybrid faces stay the same */
8995:         ++numLeavesNew;
8996:       } else if ((p >= cStart) && (p < cMax)) {
8997:         /* Interior cells add new cells and interior faces */
8998:         numLeavesNew += 4 + 3;
8999:       } else if ((p >= cMax) && (p < cEnd)) {
9000:         /* Hybrid cells add new cells and hybrid face */
9001:         numLeavesNew += 2 + 1;
9002:       }
9003:       break;
9004:     case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
9005:     case REFINER_SIMPLEX_TO_HEX_2D:
9006:       if ((p >= vStart) && (p < vEnd)) {
9007:         /* Interior vertices stay the same */
9008:         ++numLeavesNew;
9009:       } else if ((p >= fStart) && (p < fEnd)) {
9010:         /* Interior faces add new faces and vertex */
9011:         numLeavesNew += 2 + 1;
9012:       } else if ((p >= cStart) && (p < cMax)) {
9013:         /* Interior cells add new cells, interior faces, and vertex */
9014:         numLeavesNew += 3 + 3 + 1;
9015:       } else if ((p >= cMax) && (p < cEnd)) {
9016:         /* Hybrid cells add new cells, interior faces, and vertex */
9017:         numLeavesNew += 4 + 4 + 1;
9018:       }
9019:       break;
9020:     case REFINER_HEX_2D:
9021:     case REFINER_HYBRID_HEX_2D:
9022:       if ((p >= vStart) && (p < vEnd)) {
9023:         /* Interior vertices stay the same */
9024:         ++numLeavesNew;
9025:       } else if ((p >= fStart) && (p < fMax)) {
9026:         /* Interior faces add new faces and vertex */
9027:         numLeavesNew += 2 + 1;
9028:       } else if ((p >= fMax) && (p < fEnd)) {
9029:         /* Hybrid faces stay the same */
9030:         ++numLeavesNew;
9031:       } else if ((p >= cStart) && (p < cMax)) {
9032:         /* Interior cells add new cells, interior faces, and vertex */
9033:         numLeavesNew += 4 + 4 + 1;
9034:       } else if ((p >= cMax) && (p < cEnd)) {
9035:         /* Hybrid cells add new cells and hybrid face */
9036:         numLeavesNew += 2 + 1;
9037:       }
9038:       break;
9039:     case REFINER_SIMPLEX_3D:
9040:     case REFINER_HYBRID_SIMPLEX_3D:
9041:       if ((p >= vStart) && (p < vEnd)) {
9042:         /* Interior vertices stay the same */
9043:         ++numLeavesNew;
9044:       } else if ((p >= eStart) && (p < eMax)) {
9045:         /* Interior edges add new edges and vertex */
9046:         numLeavesNew += 2 + 1;
9047:       } else if ((p >= eMax) && (p < eEnd)) {
9048:         /* Hybrid edges stay the same */
9049:         ++numLeavesNew;
9050:       } else if ((p >= fStart) && (p < fMax)) {
9051:         /* Interior faces add new faces and edges */
9052:         numLeavesNew += 4 + 3;
9053:       } else if ((p >= fMax) && (p < fEnd)) {
9054:         /* Hybrid faces add new faces and edges */
9055:         numLeavesNew += 2 + 1;
9056:       } else if ((p >= cStart) && (p < cMax)) {
9057:         /* Interior cells add new cells, faces, and edges */
9058:         numLeavesNew += 8 + 8 + 1;
9059:       } else if ((p >= cMax) && (p < cEnd)) {
9060:         /* Hybrid cells add new cells and faces */
9061:         numLeavesNew += 4 + 3;
9062:       }
9063:       break;
9064:     case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
9065:     case REFINER_SIMPLEX_TO_HEX_3D:
9066:       if ((p >= vStart) && (p < vEnd)) {
9067:         /* Interior vertices stay the same */
9068:         ++numLeavesNew;
9069:       } else if ((p >= eStart) && (p < eMax)) {
9070:         /* Interior edges add new edges and vertex */
9071:         numLeavesNew += 2 + 1;
9072:       } else if ((p >= eMax) && (p < eEnd)) {
9073:         /* Hybrid edges stay the same */
9074:         ++numLeavesNew;
9075:       } else if ((p >= fStart) && (p < fMax)) {
9076:         /* Interior faces add new faces, edges and a vertex */
9077:         numLeavesNew += 3 + 3 + 1;
9078:       } else if ((p >= fMax) && (p < fEnd)) {
9079:         /* Hybrid faces add new faces and an edge */
9080:         numLeavesNew += 2 + 1;
9081:       } else if ((p >= cStart) && (p < cMax)) {
9082:         /* Interior cells add new cells, faces, edges and a vertex */
9083:         numLeavesNew += 4 + 6 + 4 + 1;
9084:       } else if ((p >= cMax) && (p < cEnd)) {
9085:         /* Hybrid cells add new cells, faces and an edge */
9086:         numLeavesNew += 3 + 3 + 1;
9087:       }
9088:       break;
9089:     case REFINER_HEX_3D:
9090:     case REFINER_HYBRID_HEX_3D:
9091:       if ((p >= vStart) && (p < vEnd)) {
9092:         /* Old vertices stay the same */
9093:         ++numLeavesNew;
9094:       } else if ((p >= eStart) && (p < eMax)) {
9095:         /* Interior edges add new edges, and vertex */
9096:         numLeavesNew += 2 + 1;
9097:       } else if ((p >= eMax) && (p < eEnd)) {
9098:         /* Hybrid edges stay the same */
9099:         ++numLeavesNew;
9100:       } else if ((p >= fStart) && (p < fMax)) {
9101:         /* Interior faces add new faces, edges, and vertex */
9102:         numLeavesNew += 4 + 4 + 1;
9103:       } else if ((p >= fMax) && (p < fEnd)) {
9104:         /* Hybrid faces add new faces and edges */
9105:         numLeavesNew += 2 + 1;
9106:       } else if ((p >= cStart) && (p < cMax)) {
9107:         /* Interior cells add new cells, faces, edges, and vertex */
9108:         numLeavesNew += 8 + 12 + 6 + 1;
9109:       } else if ((p >= cStart) && (p < cEnd)) {
9110:         /* Hybrid cells add new cells, faces, and edges */
9111:         numLeavesNew += 4 + 4 + 1;
9112:       }
9113:       break;
9114:     default:
9115:       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
9116:     }
9117:   }
9118:   /* Communicate depthSizes for each remote rank */
9119:   DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);
9120:   ISGetLocalSize(processRanks, &numNeighbors);
9121:   PetscMalloc5((depth+1)*numNeighbors,&rdepthSize,numNeighbors,&rvStartNew,numNeighbors,&reStartNew,numNeighbors,&rfStartNew,numNeighbors,&rcStartNew);
9122:   PetscMalloc7(depth+1,&depthSizeOld,(depth+1)*numNeighbors,&rdepthSizeOld,(depth+1)*numNeighbors,&rdepthMaxOld,numNeighbors,&rvStart,numNeighbors,&reStart,numNeighbors,&rfStart,numNeighbors,&rcStart);
9123:   MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);
9124:   MPI_Type_commit(&depthType);
9125:   PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);
9126:   PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);
9127:   for (n = 0; n < numNeighbors; ++n) {
9128:     GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);
9129:   }
9130:   depthSizeOld[depth]   = cMax;
9131:   depthSizeOld[0]       = vMax;
9132:   depthSizeOld[depth-1] = fMax;
9133:   depthSizeOld[1]       = eMax;

9135:   PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);
9136:   PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);

9138:   depthSizeOld[depth]   = cEnd - cStart;
9139:   depthSizeOld[0]       = vEnd - vStart;
9140:   depthSizeOld[depth-1] = fEnd - fStart;
9141:   depthSizeOld[1]       = eEnd - eStart;

9143:   PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);
9144:   PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);
9145:   for (n = 0; n < numNeighbors; ++n) {
9146:     GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);
9147:     rdepthMaxOld[n*(depth+1)+depth]   = rdepthMaxOld[n*(depth+1)+depth]   < 0 ? rdepthSizeOld[n*(depth+1)+depth]  +rcStart[n]: rdepthMaxOld[n*(depth+1)+depth];
9148:     rdepthMaxOld[n*(depth+1)+depth-1] = rdepthMaxOld[n*(depth+1)+depth-1] < 0 ? rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n]: rdepthMaxOld[n*(depth+1)+depth-1];
9149:     rdepthMaxOld[n*(depth+1)+1]       = rdepthMaxOld[n*(depth+1)+1]       < 0 ? rdepthSizeOld[n*(depth+1)+1]      +reStart[n]: rdepthMaxOld[n*(depth+1)+1];
9150:   }
9151:   MPI_Type_free(&depthType);
9152:   PetscSFDestroy(&sfProcess);
9153:   /* Calculate new point SF */
9154:   PetscMalloc1(numLeavesNew, &localPointsNew);
9155:   PetscMalloc1(numLeavesNew, &remotePointsNew);
9156:   ISGetIndices(processRanks, &neighbors);
9157:   for (l = 0, m = 0; l < numLeaves; ++l) {
9158:     PetscInt    p     = localPoints[l];
9159:     PetscInt    rp    = remotePoints[l].index, n;
9160:     PetscMPIInt rrank = remotePoints[l].rank;

9162:     PetscFindInt(rrank, numNeighbors, neighbors, &n);
9163:     if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %D", rrank);
9164:     switch (refiner) {
9165:     case REFINER_SIMPLEX_1D:
9166:       if ((p >= vStart) && (p < vEnd)) {
9167:         /* Old vertices stay the same */
9168:         localPointsNew[m]        = vStartNew     + (p  - vStart);
9169:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9170:         remotePointsNew[m].rank  = rrank;
9171:         ++m;
9172:       } else if ((p >= cStart) && (p < cMax)) {
9173:         /* Old interior cells add new cells and vertex */
9174:         for (r = 0; r < 2; ++r, ++m) {
9175:           localPointsNew[m]        = cStartNew     + (p  - cStart)*2     + r;
9176:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*2 + r;
9177:           remotePointsNew[m].rank  = rrank;
9178:         }
9179:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - cStart);
9180:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rcStart[n]);
9181:         remotePointsNew[m].rank  = rrank;
9182:         ++m;
9183:       }
9184:       break;
9185:     case REFINER_SIMPLEX_2D:
9186:     case REFINER_HYBRID_SIMPLEX_2D:
9187:       if ((p >= vStart) && (p < vEnd)) {
9188:         /* Old vertices stay the same */
9189:         localPointsNew[m]        = vStartNew     + (p  - vStart);
9190:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9191:         remotePointsNew[m].rank  = rrank;
9192:         ++m;
9193:       } else if ((p >= fStart) && (p < fMax)) {
9194:         /* Old interior faces add new faces and vertex */
9195:         for (r = 0; r < 2; ++r, ++m) {
9196:           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
9197:           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
9198:           remotePointsNew[m].rank  = rrank;
9199:         }
9200:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
9201:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
9202:         remotePointsNew[m].rank  = rrank;
9203:         ++m;
9204:       } else if ((p >= fMax) && (p < fEnd)) {
9205:         /* Old hybrid faces stay the same */
9206:         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - fMax);
9207:         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
9208:         remotePointsNew[m].rank  = rrank;
9209:         ++m;
9210:       } else if ((p >= cStart) && (p < cMax)) {
9211:         /* Old interior cells add new cells and interior faces */
9212:         for (r = 0; r < 4; ++r, ++m) {
9213:           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
9214:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
9215:           remotePointsNew[m].rank  = rrank;
9216:         }
9217:         for (r = 0; r < 3; ++r, ++m) {
9218:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - cStart)*3     + r;
9219:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r;
9220:           remotePointsNew[m].rank  = rrank;
9221:         }
9222:       } else if ((p >= cMax) && (p < cEnd)) {
9223:         /* Old hybrid cells add new cells and hybrid face */
9224:         for (r = 0; r < 2; ++r, ++m) {
9225:           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
9226:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
9227:           remotePointsNew[m].rank  = rrank;
9228:         }
9229:         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (cMax                            - cStart)*3     + (p  - cMax);
9230:         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*3 + (rp - rdepthMaxOld[n*(depth+1)+depth]);
9231:         remotePointsNew[m].rank  = rrank;
9232:         ++m;
9233:       }
9234:       break;
9235:     case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
9236:     case REFINER_SIMPLEX_TO_HEX_2D:
9237:       if ((p >= vStart) && (p < vEnd)) {
9238:         /* Old vertices stay the same */
9239:         localPointsNew[m]        = vStartNew     + (p  - vStart);
9240:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9241:         remotePointsNew[m].rank  = rrank;
9242:         ++m;
9243:       } else if ((p >= fStart) && (p < fEnd)) {
9244:         /* Old interior faces add new faces and vertex */
9245:         for (r = 0; r < 2; ++r, ++m) {
9246:           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
9247:           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
9248:           remotePointsNew[m].rank  = rrank;
9249:         }
9250:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
9251:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
9252:         remotePointsNew[m].rank  = rrank;
9253:         ++m;
9254:       } else if ((p >= cStart) && (p < cMax)) {
9255:         /* Old interior cells add new cells, interior faces, and a vertex */
9256:         for (r = 0; r < 3; ++r, ++m) {
9257:           localPointsNew[m]        = cStartNew     + (p  - cStart)*3     + r;
9258:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*3 + r;
9259:           remotePointsNew[m].rank  = rrank;
9260:         }
9261:         for (r = 0; r < 3; ++r, ++m) {
9262:           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*3     + r;
9263:           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r;
9264:           remotePointsNew[m].rank  = rrank;
9265:         }
9266:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (fEnd - fStart)                    + (p  - cStart);
9267:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]);
9268:         remotePointsNew[m].rank  = rrank;
9269:         ++m;
9270:       } else if ((p >= cMax) && (p < cEnd)) {
9271:         /* Old interior hybrid cells add new cells, interior faces, and a vertex */
9272:         for (r = 0; r < 4; ++r, ++m) {
9273:           localPointsNew[m]        = cStartNew     + (cMax  - cStart)*3                               + (p  - cMax)*4 + r;
9274:           remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*3 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
9275:           remotePointsNew[m].rank  = rrank;
9276:         }
9277:         for (r = 0; r < 4; ++r, ++m) {
9278:           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (cMax  - cStart)*3                               + (p - cMax)*4 + r;
9279:           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*3 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
9280:           remotePointsNew[m].rank  = rrank;
9281:         }
9282:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (fEnd - fStart)                    + (p  - cStart);
9283:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]);
9284:         remotePointsNew[m].rank  = rrank;
9285:         ++m;
9286:       }
9287:       break;
9288:     case REFINER_HEX_2D:
9289:     case REFINER_HYBRID_HEX_2D:
9290:       if ((p >= vStart) && (p < vEnd)) {
9291:         /* Old vertices stay the same */
9292:         localPointsNew[m]        = vStartNew     + (p  - vStart);
9293:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9294:         remotePointsNew[m].rank  = rrank;
9295:         ++m;
9296:       } else if ((p >= fStart) && (p < fMax)) {
9297:         /* Old interior faces add new faces and vertex */
9298:         for (r = 0; r < 2; ++r, ++m) {
9299:           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
9300:           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
9301:           remotePointsNew[m].rank  = rrank;
9302:         }
9303:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
9304:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
9305:         remotePointsNew[m].rank  = rrank;
9306:         ++m;
9307:       } else if ((p >= fMax) && (p < fEnd)) {
9308:         /* Old hybrid faces stay the same */
9309:         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - fMax);
9310:         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
9311:         remotePointsNew[m].rank  = rrank;
9312:         ++m;
9313:       } else if ((p >= cStart) && (p < cMax)) {
9314:         /* Old interior cells add new cells, interior faces, and vertex */
9315:         for (r = 0; r < 4; ++r, ++m) {
9316:           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
9317:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
9318:           remotePointsNew[m].rank  = rrank;
9319:         }
9320:         for (r = 0; r < 4; ++r, ++m) {
9321:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - cStart)*4     + r;
9322:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*4 + r;
9323:           remotePointsNew[m].rank  = rrank;
9324:         }
9325:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)               + (fMax                              - fStart)     + (p  - cStart);
9326:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0]  + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]);
9327:         remotePointsNew[m].rank  = rrank;
9328:         ++m;
9329:       } else if ((p >= cStart) && (p < cMax)) {
9330:         /* Old hybrid cells add new cells and hybrid face */
9331:         for (r = 0; r < 2; ++r, ++m) {
9332:           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r; /* TODO: is this a bug? */
9333:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; /* TODO: is this a bug? */
9334:           remotePointsNew[m].rank  = rrank;
9335:         }
9336:         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (cMax                            - cStart)*4     + (p  - cMax);
9337:         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*4 + (rp - rdepthMaxOld[n*(depth+1)+depth]);
9338:         remotePointsNew[m].rank  = rrank;
9339:         ++m;
9340:       }
9341:       break;
9342:     case REFINER_SIMPLEX_3D:
9343:     case REFINER_HYBRID_SIMPLEX_3D:
9344:       if ((p >= vStart) && (p < vEnd)) {
9345:         /* Interior vertices stay the same */
9346:         localPointsNew[m]        = vStartNew     + (p  - vStart);
9347:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9348:         remotePointsNew[m].rank  = rrank;
9349:         ++m;
9350:       } else if ((p >= eStart) && (p < eMax)) {
9351:         /* Interior edges add new edges and vertex */
9352:         for (r = 0; r < 2; ++r, ++m) {
9353:           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
9354:           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
9355:           remotePointsNew[m].rank  = rrank;
9356:         }
9357:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
9358:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
9359:         remotePointsNew[m].rank  = rrank;
9360:         ++m;
9361:       } else if ((p >= eMax) && (p < eEnd)) {
9362:         /* Hybrid edges stay the same */
9363:         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (cMax                            - cStart)     + (p  - eMax);
9364:         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*3 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n]) + (rp - rdepthMaxOld[n*(depth+1)+1]);
9365:         remotePointsNew[m].rank  = rrank;
9366:         ++m;
9367:       } else if ((p >= fStart) && (p < fMax)) {
9368:         /* Interior faces add new faces and edges */
9369:         for (r = 0; r < 4; ++r, ++m) {
9370:           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
9371:           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
9372:           remotePointsNew[m].rank  = rrank;
9373:         }
9374:         for (r = 0; r < 3; ++r, ++m) {
9375:           localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (p  - fStart)*3     + r;
9376:           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*3 + r;
9377:           remotePointsNew[m].rank  = rrank;
9378:         }
9379:       } else if ((p >= fMax) && (p < fEnd)) {
9380:         /* Hybrid faces add new faces and edges */
9381:         for (r = 0; r < 2; ++r, ++m) {
9382:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (p  - fMax)*2                              + r;
9383:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth-1])*2 + r;
9384:           remotePointsNew[m].rank  = rrank;
9385:         }
9386:         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (cMax                            - cStart)     + (eEnd                                    - eMax)                        + (p  - fMax);
9387:         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*3 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n]) + (rdepthSizeOld[n*(depth+1)+1]+reStart[n] - rdepthMaxOld[n*(depth+1)+1]) + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
9388:         remotePointsNew[m].rank  = rrank;
9389:         ++m;
9390:       } else if ((p >= cStart) && (p < cMax)) {
9391:         /* Interior cells add new cells, faces, and edges */
9392:         for (r = 0; r < 8; ++r, ++m) {
9393:           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
9394:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
9395:           remotePointsNew[m].rank  = rrank;
9396:         }
9397:         for (r = 0; r < 8; ++r, ++m) {
9398:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (p  - cStart)*8     + r;
9399:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*8 + r;
9400:           remotePointsNew[m].rank  = rrank;
9401:         }
9402:         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (p  - cStart)*1     + 0;
9403:         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*3 + (rp - rcStart[n])*1 + 0;
9404:         remotePointsNew[m].rank  = rrank;
9405:         ++m;
9406:       } else if ((p >= cMax) && (p < cEnd)) {
9407:         /* Hybrid cells add new cells and faces */
9408:         for (r = 0; r < 4; ++r, ++m) {
9409:           localPointsNew[m]        = cStartNew     + (cMax                            - cStart)*8     + (p  - cMax)*4                            + r;
9410:           remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
9411:           remotePointsNew[m].rank  = rrank;
9412:         }
9413:         for (r = 0; r < 3; ++r, ++m) {
9414:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*8     + (fEnd                                          - fMax)*2                              + (p  - cMax)*3                            + r;
9415:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth])*3 + r;
9416:           remotePointsNew[m].rank  = rrank;
9417:         }
9418:       }
9419:       break;
9420:     case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
9421:     case REFINER_SIMPLEX_TO_HEX_3D:
9422:       if ((p >= vStart) && (p < vEnd)) {
9423:         /* Interior vertices stay the same */
9424:         localPointsNew[m]        = vStartNew     + (p  - vStart);
9425:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9426:         remotePointsNew[m].rank  = rrank;
9427:         ++m;
9428:       } else if ((p >= eStart) && (p < eMax)) {
9429:         /* Interior edges add new edges and vertex */
9430:         for (r = 0; r < 2; ++r, ++m) {
9431:           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
9432:           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
9433:           remotePointsNew[m].rank  = rrank;
9434:         }
9435:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
9436:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
9437:         remotePointsNew[m].rank  = rrank;
9438:         ++m;
9439:       } else if ((p >= eMax) && (p < eEnd)) {
9440:         /* Hybrid edges stay the same */
9441:         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*3     + (cMax                            - cStart)*4     + (p  - eMax);
9442:         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*3 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*4 + (rp - rdepthMaxOld[n*(depth+1)+1]);
9443:         remotePointsNew[m].rank  = rrank;
9444:         ++m;
9445:       } else if ((p >= fStart) && (p < fMax)) {
9446:         /* Interior faces add new faces, edges and a vertex */
9447:         for (r = 0; r < 3; ++r, ++m) {
9448:           localPointsNew[m]        = fStartNew     + (p  - fStart)*3     + r;
9449:           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*3 + r;
9450:           remotePointsNew[m].rank  = rrank;
9451:         }
9452:         for (r = 0; r < 3; ++r, ++m) {
9453:           localPointsNew[m]        = eStartNew     + (eMax - eStart)*2                            + (p  - fStart)*3     + r;
9454:           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*3 + r;
9455:           remotePointsNew[m].rank  = rrank;
9456:         }
9457:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (eMax - eStart)                            + (p - fStart);
9458:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rp - rfStart[n]);
9459:         remotePointsNew[m].rank  = rrank;
9460:         ++m;
9461:       } else if ((p >= fMax) && (p < fEnd)) {
9462:         /* Interior hybrid faces add new faces and an edge */
9463:         for (r = 0; r < 2; ++r, ++m) {
9464:           localPointsNew[m]        = fStartNew     + (fMax - fStart)*3                                 + (cMax - cStart)*6                                + (p  - fMax)*2 + r;
9465:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1]- rfStart[n])*3 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*6 + (rp - rdepthMaxOld[n*(depth+1)+depth-1])*2 + r;
9466:           remotePointsNew[m].rank  = rrank;
9467:         }
9468:         localPointsNew[m]        = eStartNew     + (eMax - eStart)*2                            + (fMax - fStart)*3                                 + (cMax - cStart)*4                                + (eEnd - eMax)                                                           + (p  - fMax);
9469:         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1]- rfStart[n])*3 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*4 + (rdepthSizeOld[n*(depth+1)+1]+reStart[n] - rdepthMaxOld[n*(depth+1)+1]) + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
9470:         remotePointsNew[m].rank  = rrank;
9471:         ++m;
9472:       } else if ((p >= cStart) && (p < cMax)) {
9473:         /* Interior cells add new cells, faces, edges, and a vertex */
9474:         for (r = 0; r < 4; ++r, ++m) {
9475:           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
9476:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
9477:           remotePointsNew[m].rank  = rrank;
9478:         }
9479:         for (r = 0; r < 6; ++r, ++m) {
9480:           localPointsNew[m]        = fStartNew     + (fMax - fStart)*3                                 + (p  - cStart)*6     + r;
9481:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1]- rfStart[n])*3 + (rp - rcStart[n])*6 + r;
9482:           remotePointsNew[m].rank  = rrank;
9483:         }
9484:         for (r = 0; r < 4; ++r, ++m) {
9485:           localPointsNew[m]        = eStartNew     + (eMax - eStart)*2                           + (fMax - fStart)*3                                 + (p  - cStart)*4 + r;
9486:           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1]- reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1]- rfStart[n])*3 + (rp - rcStart[n])*4 + r;
9487:           remotePointsNew[m].rank  = rrank;
9488:         }
9489:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (eMax - eStart)                           + (fMax - fStart)                                 + (p  - cStart);
9490:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+1]- reStart[n]) + (rdepthMaxOld[n*(depth+1)+depth-1]- rfStart[n]) + (rp - rcStart[n]);
9491:         remotePointsNew[m].rank  = rrank;
9492:         ++m;
9493:       } else if ((p >= cMax) && (p < cEnd)) {
9494:         /* Interior hybrid cells add new cells, faces and an edge */
9495:         for (r = 0; r < 3; ++r, ++m) {
9496:           localPointsNew[m]        = cStartNew     + (cMax                            - cStart)*4     + (p  - cMax)*3                            + r;
9497:           remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*4 + (rp - rdepthMaxOld[n*(depth+1)+depth])*3 + r;
9498:           remotePointsNew[m].rank  = rrank;
9499:         }
9500:         for (r = 0; r < 3; ++r, ++m) {
9501:           localPointsNew[m]        = fStartNew     + (fMax - fStart)*3                                 + (cMax - cStart)*6                                + (fEnd  - fMax)*2                                                                      + (p  - cMax)*3 + r;
9502:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1]- rfStart[n])*3 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*6 + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth])*3 + r;
9503:           remotePointsNew[m].rank  = rrank;
9504:         }
9505:         localPointsNew[m]        = eStartNew     + (eMax - eStart)*2                           + (fMax - fStart)*3                                 + (cMax - cStart)*4                                + (eEnd  - eMax)                                                          + (fEnd  - fMax)                                                                      + (p  - cMax);
9506:         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1]- reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1]- rfStart[n])*3 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*4 + (rdepthSizeOld[n*(depth+1)+1]+reStart[n] - rdepthMaxOld[n*(depth+1)+1]) + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1]) + (rp - rdepthMaxOld[n*(depth+1)+depth]);
9507:         remotePointsNew[m].rank  = rrank;
9508:         ++m;
9509:       }
9510:       break;
9511:     case REFINER_HEX_3D:
9512:     case REFINER_HYBRID_HEX_3D:
9513:       if ((p >= vStart) && (p < vEnd)) {
9514:         /* Interior vertices stay the same */
9515:         localPointsNew[m]        = vStartNew     + (p  - vStart);
9516:         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
9517:         remotePointsNew[m].rank  = rrank;
9518:         ++m;
9519:       } else if ((p >= eStart) && (p < eMax)) {
9520:         /* Interior edges add new edges and vertex */
9521:         for (r = 0; r < 2; ++r, ++m) {
9522:           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
9523:           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
9524:           remotePointsNew[m].rank  = rrank;
9525:         }
9526:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
9527:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
9528:         remotePointsNew[m].rank  = rrank;
9529:         ++m;
9530:       } else if ((p >= eMax) && (p < eEnd)) {
9531:         /* Hybrid edges stay the same */
9532:         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (cMax                            - cStart)*6     + (p  - eMax);
9533:         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*6 + (rp - rdepthMaxOld[n*(depth+1)+1]);
9534:         remotePointsNew[m].rank  = rrank;
9535:         ++m;
9536:       } else if ((p >= fStart) && (p < fMax)) {
9537:         /* Interior faces add new faces, edges, and vertex */
9538:         for (r = 0; r < 4; ++r, ++m) {
9539:           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
9540:           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
9541:           remotePointsNew[m].rank  = rrank;
9542:         }
9543:         for (r = 0; r < 4; ++r, ++m) {
9544:           localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (p  - fStart)*4     + r;
9545:           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*4 + r;
9546:           remotePointsNew[m].rank  = rrank;
9547:         }
9548:         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (eMax                        - eStart)     + (p  - fStart);
9549:         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rp - rfStart[n]);
9550:         remotePointsNew[m].rank  = rrank;
9551:         ++m;
9552:       } else if ((p >= fMax) && (p < fEnd)) {
9553:         /* Hybrid faces add new faces and edges */
9554:         for (r = 0; r < 2; ++r, ++m) {
9555:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*12     + (p  - fMax)*2                              + r;
9556:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*12 + (rp - rdepthMaxOld[n*(depth+1)+depth-1])*2 + r;
9557:           remotePointsNew[m].rank  = rrank;
9558:         }
9559:         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (cMax                            - cStart)*6     + (eEnd                                    - eMax)                        + (p  - fMax);
9560:         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*6 + (rdepthSizeOld[n*(depth+1)+1]+reStart[n] - rdepthMaxOld[n*(depth+1)+1]) + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
9561:         remotePointsNew[m].rank  = rrank;
9562:         ++m;
9563:       } else if ((p >= cStart) && (p < cMax)) {
9564:         /* Interior cells add new cells, faces, edges, and vertex */
9565:         for (r = 0; r < 8; ++r, ++m) {
9566:           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
9567:           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
9568:           remotePointsNew[m].rank  = rrank;
9569:         }
9570:         for (r = 0; r < 12; ++r, ++m) {
9571:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (p  - cStart)*12     + r;
9572:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*12 + r;
9573:           remotePointsNew[m].rank  = rrank;
9574:         }
9575:         for (r = 0; r < 6; ++r, ++m) {
9576:           localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (p  - cStart)*6     + r;
9577:           remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*6 + r;
9578:           remotePointsNew[m].rank  = rrank;
9579:         }
9580:         for (r = 0; r < 1; ++r, ++m) {
9581:           localPointsNew[m]        = vStartNew     + (eMax                        - eStart)     + (fMax                              - fStart)     + (p  - cStart)     + r;
9582:           remotePointsNew[m].index = rvStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]) + r;
9583:           remotePointsNew[m].rank  = rrank;
9584:         }
9585:       } else if ((p >= cMax) && (p < cEnd)) {
9586:         /* Hybrid cells add new cells, faces, and edges */
9587:         for (r = 0; r < 4; ++r, ++m) {
9588:           localPointsNew[m]        = cStartNew     + (cMax                            - cStart)*8     + (p  - cMax)*4                            + r;
9589:           remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
9590:           remotePointsNew[m].rank  = rrank;
9591:         }
9592:         for (r = 0; r < 4; ++r, ++m) {
9593:           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*4     + (cMax                            - cStart)*12     + (fEnd                                          - fMax)*2                              + (p  - cMax)*4                            + r;
9594:           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*12 + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
9595:           remotePointsNew[m].rank  = rrank;
9596:         }
9597:         localPointsNew[m]        = eStartNew     + (eMax                        - eStart)*2     + (fMax                              - fStart)*4     + (cMax                            - cStart)*6     + (eEnd                                    - eMax)                        + (fEnd                                          - fMax)                              + (p  - cMax);
9598:         remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*6 + (rdepthSizeOld[n*(depth+1)+1]+reStart[n] - rdepthMaxOld[n*(depth+1)+1]) + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1]) + (rp - rdepthMaxOld[n*(depth+1)+depth]);
9599:         remotePointsNew[m].rank  = rrank;
9600:         ++m;
9601:       }
9602:       break;
9603:     default:
9604:       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
9605:     }
9606:   }
9607:   if (m != numLeavesNew) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of leaf point %D should be %D", m, numLeavesNew);
9608:   ISRestoreIndices(processRanks, &neighbors);
9609:   ISDestroy(&processRanks);
9610:   {
9611:     PetscSFNode *rp, *rtmp;
9612:     PetscInt    *lp, *idx, *ltmp, i;

9614:     /* SF needs sorted leaves to correct calculate Gather */
9615:     PetscMalloc1(numLeavesNew,&idx);
9616:     PetscMalloc1(numLeavesNew, &lp);
9617:     PetscMalloc1(numLeavesNew, &rp);
9618:     for (i = 0; i < numLeavesNew; ++i) {
9619:       if ((localPointsNew[i] < pStartNew) || (localPointsNew[i] >= pEndNew)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local SF point %D (%D) not in [%D, %D)", localPointsNew[i], i, pStartNew, pEndNew);
9620:       idx[i] = i;
9621:     }
9622:     PetscSortIntWithPermutation(numLeavesNew, localPointsNew, idx);
9623:     for (i = 0; i < numLeavesNew; ++i) {
9624:       lp[i] = localPointsNew[idx[i]];
9625:       rp[i] = remotePointsNew[idx[i]];
9626:     }
9627:     ltmp            = localPointsNew;
9628:     localPointsNew  = lp;
9629:     rtmp            = remotePointsNew;
9630:     remotePointsNew = rp;
9631:     PetscFree(idx);
9632:     PetscFree(ltmp);
9633:     PetscFree(rtmp);
9634:   }
9635:   PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);
9636:   PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);
9637:   PetscFree7(depthSizeOld,rdepthSizeOld,rdepthMaxOld,rvStart,reStart,rfStart,rcStart);
9638:   return(0);
9639: }

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

9649:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
9650:   DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
9651:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
9652:   DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
9653:   DMPlexGetDepth(dm, &depth);
9654:   if (refiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
9655:   DMGetNumLabels(dm, &numLabels);
9656:   DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
9657:   switch (refiner) {
9658:   case REFINER_NOOP:
9659:   case REFINER_SIMPLEX_1D:
9660:   case REFINER_SIMPLEX_2D:
9661:   case REFINER_SIMPLEX_TO_HEX_2D:
9662:   case REFINER_HEX_2D:
9663:   case REFINER_SIMPLEX_3D:
9664:   case REFINER_HEX_3D:
9665:   case REFINER_SIMPLEX_TO_HEX_3D:
9666:     break;
9667:   case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
9668:   case REFINER_HYBRID_SIMPLEX_3D:
9669:   case REFINER_HYBRID_HEX_3D:
9670:     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
9671:   case REFINER_HYBRID_SIMPLEX_2D:
9672:   case REFINER_HYBRID_HEX_2D:
9673:     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
9674:   case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
9675:     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
9676:     break;
9677:   default:
9678:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
9679:   }
9680:   cMax = cMax < 0 ? cEnd : cMax;
9681:   fMax = fMax < 0 ? fEnd : fMax;
9682:   eMax = eMax < 0 ? eEnd : eMax;
9683:   for (l = 0; l < numLabels; ++l) {
9684:     DMLabel         label, labelNew;
9685:     const char     *lname;
9686:     PetscBool       isDepth;
9687:     IS              valueIS;
9688:     const PetscInt *values;
9689:     PetscInt        defVal;
9690:     PetscInt        numValues, val;

9692:     DMGetLabelName(dm, l, &lname);
9693:     PetscStrcmp(lname, "depth", &isDepth);
9694:     if (isDepth) continue;
9695:     DMCreateLabel(rdm, lname);
9696:     DMGetLabel(dm, lname, &label);
9697:     DMGetLabel(rdm, lname, &labelNew);
9698:     DMLabelGetDefaultValue(label,&defVal);
9699:     DMLabelSetDefaultValue(labelNew,defVal);
9700:     DMLabelGetValueIS(label, &valueIS);
9701:     ISGetLocalSize(valueIS, &numValues);
9702:     ISGetIndices(valueIS, &values);
9703:     for (val = 0; val < numValues; ++val) {
9704:       IS              pointIS;
9705:       const PetscInt *points;
9706:       PetscInt        numPoints, n;

9708:       DMLabelGetStratumIS(label, values[val], &pointIS);
9709:       ISGetLocalSize(pointIS, &numPoints);
9710:       ISGetIndices(pointIS, &points);
9711:       /* Ensure refined label is created with same number of strata as
9712:        * original (even if no entries here). */
9713:       DMLabelAddStratum(labelNew, values[val]);
9714:       for (n = 0; n < numPoints; ++n) {
9715:         const PetscInt p = points[n];
9716:         switch (refiner) {
9717:         case REFINER_SIMPLEX_1D:
9718:           if ((p >= vStart) && (p < vEnd)) {
9719:             /* Old vertices stay the same */
9720:             newp = vStartNew + (p - vStart);
9721:             DMLabelSetValue(labelNew, newp, values[val]);
9722:           } else if ((p >= cStart) && (p < cEnd)) {
9723:             /* Old cells add new cells and vertex */
9724:             newp = vStartNew + (vEnd - vStart) + (p - cStart);
9725:             DMLabelSetValue(labelNew, newp, values[val]);
9726:             for (r = 0; r < 2; ++r) {
9727:               newp = cStartNew + (p - cStart)*2 + r;
9728:               DMLabelSetValue(labelNew, newp, values[val]);
9729:             }
9730:           }
9731:           break;
9732:         case REFINER_SIMPLEX_2D:
9733:           if ((p >= vStart) && (p < vEnd)) {
9734:             /* Old vertices stay the same */
9735:             newp = vStartNew + (p - vStart);
9736:             DMLabelSetValue(labelNew, newp, values[val]);
9737:           } else if ((p >= fStart) && (p < fEnd)) {
9738:             /* Old faces add new faces and vertex */
9739:             newp = vStartNew + (vEnd - vStart) + (p - fStart);
9740:             DMLabelSetValue(labelNew, newp, values[val]);
9741:             for (r = 0; r < 2; ++r) {
9742:               newp = fStartNew + (p - fStart)*2 + r;
9743:               DMLabelSetValue(labelNew, newp, values[val]);
9744:             }
9745:           } else if ((p >= cStart) && (p < cEnd)) {
9746:             /* Old cells add new cells and interior faces */
9747:             for (r = 0; r < 4; ++r) {
9748:               newp = cStartNew + (p - cStart)*4 + r;
9749:               DMLabelSetValue(labelNew, newp, values[val]);
9750:             }
9751:             for (r = 0; r < 3; ++r) {
9752:               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
9753:               DMLabelSetValue(labelNew, newp, values[val]);
9754:             }
9755:           }
9756:           break;
9757:         case REFINER_HYBRID_SIMPLEX_TO_HEX_2D:
9758:         case REFINER_SIMPLEX_TO_HEX_2D:
9759:           if ((p >= vStart) && (p < vEnd)) {
9760:             /* Old vertices stay the same */
9761:             newp = vStartNew + (p - vStart);
9762:             DMLabelSetValue(labelNew, newp, values[val]);
9763:           } else if ((p >= fStart) && (p < fEnd)) {
9764:             /* Old faces add new faces and vertex */
9765:             newp = vStartNew + (vEnd - vStart) + (p - fStart);
9766:             DMLabelSetValue(labelNew, newp, values[val]);
9767:             for (r = 0; r < 2; ++r) {
9768:               newp = fStartNew + (p - fStart)*2 + r;
9769:               DMLabelSetValue(labelNew, newp, values[val]);
9770:             }
9771:           } else if ((p >= cStart) && (p < cMax)) {
9772:             /* Old cells add new cells, interior faces, and a vertex */
9773:             for (r = 0; r < 3; ++r) {
9774:               newp = cStartNew + (p - cStart)*3 + r;
9775:               DMLabelSetValue(labelNew, newp, values[val]);
9776:             }
9777:             for (r = 0; r < 3; ++r) {
9778:               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
9779:               DMLabelSetValue(labelNew, newp, values[val]);
9780:             }
9781:             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + p;
9782:             DMLabelSetValue(labelNew, newp, values[val]);
9783:           } else if ((p >= cMax) && (p < cEnd)) {
9784:             /* Old hybrid cells add new cells, interior faces, and a vertex */
9785:             for (r = 0; r < 4; ++r) {
9786:               newp = cStartNew + (cMax - cStart)*3 + (p - cMax)*4 + r;
9787:               DMLabelSetValue(labelNew, newp, values[val]);
9788:             }
9789:             for (r = 0; r < 4; ++r) {
9790:               newp = fStartNew + (fEnd - fStart)*2 + (cMax - cStart)*3 + (p - cMax)*4 + r;
9791:               DMLabelSetValue(labelNew, newp, values[val]);
9792:             }
9793:             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + p;
9794:             DMLabelSetValue(labelNew, newp, values[val]);
9795:           }
9796:           break;
9797:         case REFINER_HEX_2D:
9798:           if ((p >= vStart) && (p < vEnd)) {
9799:             /* Old vertices stay the same */
9800:             newp = vStartNew + (p - vStart);
9801:             DMLabelSetValue(labelNew, newp, values[val]);
9802:           } else if ((p >= fStart) && (p < fEnd)) {
9803:             /* Old faces add new faces and vertex */
9804:             newp = vStartNew + (vEnd - vStart) + (p - fStart);
9805:             DMLabelSetValue(labelNew, newp, values[val]);
9806:             for (r = 0; r < 2; ++r) {
9807:               newp = fStartNew + (p - fStart)*2 + r;
9808:               DMLabelSetValue(labelNew, newp, values[val]);
9809:             }
9810:           } else if ((p >= cStart) && (p < cEnd)) {
9811:             /* Old cells add new cells and interior faces and vertex */
9812:             for (r = 0; r < 4; ++r) {
9813:               newp = cStartNew + (p - cStart)*4 + r;
9814:               DMLabelSetValue(labelNew, newp, values[val]);
9815:             }
9816:             for (r = 0; r < 4; ++r) {
9817:               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
9818:               DMLabelSetValue(labelNew, newp, values[val]);
9819:             }
9820:             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
9821:             DMLabelSetValue(labelNew, newp, values[val]);
9822:           }
9823:           break;
9824:         case REFINER_HYBRID_SIMPLEX_2D:
9825:           if ((p >= vStart) && (p < vEnd)) {
9826:             /* Old vertices stay the same */
9827:             newp = vStartNew + (p - vStart);
9828:             DMLabelSetValue(labelNew, newp, values[val]);
9829:           } else if ((p >= fStart) && (p < fMax)) {
9830:             /* Old interior faces add new faces and vertex */
9831:             newp = vStartNew + (vEnd - vStart) + (p - fStart);
9832:             DMLabelSetValue(labelNew, newp, values[val]);
9833:             for (r = 0; r < 2; ++r) {
9834:               newp = fStartNew + (p - fStart)*2 + r;
9835:               DMLabelSetValue(labelNew, newp, values[val]);
9836:             }
9837:           } else if ((p >= fMax) && (p < fEnd)) {
9838:             /* Old hybrid faces stay the same */
9839:             newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
9840:             DMLabelSetValue(labelNew, newp, values[val]);
9841:           } else if ((p >= cStart) && (p < cMax)) {
9842:             /* Old interior cells add new cells and interior faces */
9843:             for (r = 0; r < 4; ++r) {
9844:               newp = cStartNew + (p - cStart)*4 + r;
9845:               DMLabelSetValue(labelNew, newp, values[val]);
9846:             }
9847:             for (r = 0; r < 3; ++r) {
9848:               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
9849:               DMLabelSetValue(labelNew, newp, values[val]);
9850:             }
9851:           } else if ((p >= cMax) && (p < cEnd)) {
9852:             /* Old hybrid cells add new cells and hybrid face */
9853:             for (r = 0; r < 2; ++r) {
9854:               newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
9855:               DMLabelSetValue(labelNew, newp, values[val]);
9856:             }
9857:             newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
9858:             DMLabelSetValue(labelNew, newp, values[val]);
9859:           }
9860:           break;
9861:         case REFINER_HYBRID_HEX_2D:
9862:           if ((p >= vStart) && (p < vEnd)) {
9863:             /* Old vertices stay the same */
9864:             newp = vStartNew + (p - vStart);
9865:             DMLabelSetValue(labelNew, newp, values[val]);
9866:           } else if ((p >= fStart) && (p < fMax)) {
9867:             /* Old interior faces add new faces and vertex */
9868:             newp = vStartNew + (vEnd - vStart) + (p - fStart);
9869:             DMLabelSetValue(labelNew, newp, values[val]);
9870:             for (r = 0; r < 2; ++r) {
9871:               newp = fStartNew + (p - fStart)*2 + r;
9872:               DMLabelSetValue(labelNew, newp, values[val]);
9873:             }
9874:           } else if ((p >= fMax) && (p < fEnd)) {
9875:             /* Old hybrid faces stay the same */
9876:             newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
9877:             DMLabelSetValue(labelNew, newp, values[val]);
9878:           } else if ((p >= cStart) && (p < cMax)) {
9879:             /* Old interior cells add new cells, interior faces, and vertex */
9880:             for (r = 0; r < 4; ++r) {
9881:               newp = cStartNew + (p - cStart)*4 + r;
9882:               DMLabelSetValue(labelNew, newp, values[val]);
9883:             }
9884:             for (r = 0; r < 4; ++r) {
9885:               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
9886:               DMLabelSetValue(labelNew, newp, values[val]);
9887:             }
9888:             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
9889:             DMLabelSetValue(labelNew, newp, values[val]);
9890:           } else if ((p >= cMax) && (p < cEnd)) {
9891:             /* Old hybrid cells add new cells and hybrid face */
9892:             for (r = 0; r < 2; ++r) {
9893:               newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
9894:               DMLabelSetValue(labelNew, newp, values[val]);
9895:             }
9896:             newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (p - cMax);
9897:             DMLabelSetValue(labelNew, newp, values[val]);
9898:           }
9899:           break;
9900:         case REFINER_SIMPLEX_3D:
9901:           if ((p >= vStart) && (p < vEnd)) {
9902:             /* Old vertices stay the same */
9903:             newp = vStartNew + (p - vStart);
9904:             DMLabelSetValue(labelNew, newp, values[val]);
9905:           } else if ((p >= eStart) && (p < eEnd)) {
9906:             /* Old edges add new edges and vertex */
9907:             for (r = 0; r < 2; ++r) {
9908:               newp = eStartNew + (p - eStart)*2 + r;
9909:               DMLabelSetValue(labelNew, newp, values[val]);
9910:             }
9911:             newp = vStartNew + (vEnd - vStart) + (p - eStart);
9912:             DMLabelSetValue(labelNew, newp, values[val]);
9913:           } else if ((p >= fStart) && (p < fEnd)) {
9914:             /* Old faces add new faces and edges */
9915:             for (r = 0; r < 4; ++r) {
9916:               newp = fStartNew + (p - fStart)*4 + r;
9917:               DMLabelSetValue(labelNew, newp, values[val]);
9918:             }
9919:             for (r = 0; r < 3; ++r) {
9920:               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
9921:               DMLabelSetValue(labelNew, newp, values[val]);
9922:             }
9923:           } else if ((p >= cStart) && (p < cEnd)) {
9924:             /* Old cells add new cells and interior faces and edges */
9925:             for (r = 0; r < 8; ++r) {
9926:               newp = cStartNew + (p - cStart)*8 + r;
9927:               DMLabelSetValue(labelNew, newp, values[val]);
9928:             }
9929:             for (r = 0; r < 8; ++r) {
9930:               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*8 + r;
9931:               DMLabelSetValue(labelNew, newp, values[val]);
9932:             }
9933:             for (r = 0; r < 1; ++r) {
9934:               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*1 + r;
9935:               DMLabelSetValue(labelNew, newp, values[val]);
9936:             }
9937:           }
9938:           break;
9939:         case REFINER_HYBRID_SIMPLEX_TO_HEX_3D:
9940:         case REFINER_SIMPLEX_TO_HEX_3D:
9941:           if ((p >= vStart) && (p < vEnd)) {
9942:             /* Old vertices stay the same */
9943:             newp = vStartNew + (p - vStart);
9944:             DMLabelSetValue(labelNew, newp, values[val]);
9945:           } else if ((p >= eStart) && (p < eMax)) {
9946:             /* Interior edges add new edges and vertex */
9947:             for (r = 0; r < 2; ++r) {
9948:               newp = eStartNew + (p - eStart)*2 + r;
9949:               DMLabelSetValue(labelNew, newp, values[val]);
9950:             }
9951:             newp = vStartNew + (vEnd - vStart) + (p - eStart);
9952:             DMLabelSetValue(labelNew, newp, values[val]);
9953:           } else if ((p >= eMax) && (p < eEnd)) {
9954:             /* Hybrid edges stay the same */
9955:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + p - eMax;
9956:             DMLabelSetValue(labelNew, newp, values[val]);
9957:           } else if ((p >= fStart) && (p < fMax)) {
9958:             /* Old faces add new faces, edges and a vertex */
9959:             for (r = 0; r < 3; ++r) {
9960:               newp = fStartNew + (p - fStart)*3 + r;
9961:               DMLabelSetValue(labelNew, newp, values[val]);
9962:             }
9963:             for (r = 0; r < 3; ++r) {
9964:               newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
9965:               DMLabelSetValue(labelNew, newp, values[val]);
9966:             }
9967:           } else if ((p >= fMax) && (p < fEnd)) {
9968:             /* Old hybrid faces add new faces and an edge */
9969:             for (r = 0; r < 2; ++r) {
9970:               newp = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (p - fMax)*2 + r;
9971:               DMLabelSetValue(labelNew, newp, values[val]);
9972:             }
9973:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (p - fMax);
9974:             DMLabelSetValue(labelNew, newp, values[val]);
9975:           } else if ((p >= cStart) && (p < cMax)) {
9976:             /* Old cells add new cells and interior faces and edges and a vertex */
9977:             for (r = 0; r < 4; ++r) {
9978:               newp = cStartNew + (p - cStart)*4 + r;
9979:               DMLabelSetValue(labelNew, newp, values[val]);
9980:             }
9981:             for (r = 0; r < 6; ++r) {
9982:               newp = fStartNew + (fMax - fStart)*3 + (p - cStart)*6 + r;
9983:               DMLabelSetValue(labelNew, newp, values[val]);
9984:             }
9985:             for (r = 0; r < 4; ++r) {
9986:               newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart)*4 + r;
9987:               DMLabelSetValue(labelNew, newp, values[val]);
9988:             }
9989:             newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + p - cStart;
9990:             DMLabelSetValue(labelNew, newp, values[val]);
9991:           } else if ((p >= cMax) && (p < cEnd)) {
9992:             /* Old hybrid cells add new cells and interior faces and an edge */
9993:             for (r = 0; r < 3; ++r) {
9994:               newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*3 + r;
9995:               DMLabelSetValue(labelNew, newp, values[val]);
9996:             }
9997:             for (r = 0; r < 3; ++r) {
9998:               newp = fStartNew + (fMax - fStart)*3 + (cMax - cStart)*6 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
9999:               DMLabelSetValue(labelNew, newp, values[val]);
10000:             }
10001:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart)*4 + (eEnd - eMax) + (fEnd - fMax) + p - cMax;
10002:             DMLabelSetValue(labelNew, newp, values[val]);
10003:           }
10004:           break;
10005:         case REFINER_HYBRID_SIMPLEX_3D:
10006:           if ((p >= vStart) && (p < vEnd)) {
10007:             /* Interior vertices stay the same */
10008:             newp = vStartNew + (p - vStart);
10009:             DMLabelSetValue(labelNew, newp, values[val]);
10010:           } else if ((p >= eStart) && (p < eMax)) {
10011:             /* Interior edges add new edges and vertex */
10012:             for (r = 0; r < 2; ++r) {
10013:               newp = eStartNew + (p - eStart)*2 + r;
10014:               DMLabelSetValue(labelNew, newp, values[val]);
10015:             }
10016:             newp = vStartNew + (vEnd - vStart) + (p - eStart);
10017:             DMLabelSetValue(labelNew, newp, values[val]);
10018:           } else if ((p >= eMax) && (p < eEnd)) {
10019:             /* Hybrid edges stay the same */
10020:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - eMax);
10021:             DMLabelSetValue(labelNew, newp, values[val]);
10022:           } else if ((p >= fStart) && (p < fMax)) {
10023:             /* Interior faces add new faces and edges */
10024:             for (r = 0; r < 4; ++r) {
10025:               newp = fStartNew + (p - fStart)*4 + r;
10026:               DMLabelSetValue(labelNew, newp, values[val]);
10027:             }
10028:             for (r = 0; r < 3; ++r) {
10029:               newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
10030:               DMLabelSetValue(labelNew, newp, values[val]);
10031:             }
10032:           } else if ((p >= fMax) && (p < fEnd)) {
10033:             /* Hybrid faces add new faces and edges */
10034:             for (r = 0; r < 2; ++r) {
10035:               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (p - fMax)*2 + r;
10036:               DMLabelSetValue(labelNew, newp, values[val]);
10037:             }
10038:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - fMax);
10039:             DMLabelSetValue(labelNew, newp, values[val]);
10040:           } else if ((p >= cStart) && (p < cMax)) {
10041:             /* Interior cells add new cells, faces, and edges */
10042:             for (r = 0; r < 8; ++r) {
10043:               newp = cStartNew + (p - cStart)*8 + r;
10044:               DMLabelSetValue(labelNew, newp, values[val]);
10045:             }
10046:             for (r = 0; r < 8; ++r) {
10047:               newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*8 + r;
10048:               DMLabelSetValue(labelNew, newp, values[val]);
10049:             }
10050:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart);
10051:             DMLabelSetValue(labelNew, newp, values[val]);
10052:           } else if ((p >= cMax) && (p < cEnd)) {
10053:             /* Hybrid cells add new cells and faces */
10054:             for (r = 0; r < 4; ++r) {
10055:               newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
10056:               DMLabelSetValue(labelNew, newp, values[val]);
10057:             }
10058:             for (r = 0; r < 3; ++r) {
10059:               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
10060:               DMLabelSetValue(labelNew, newp, values[val]);
10061:             }
10062:           }
10063:           break;
10064:         case REFINER_HEX_3D:
10065:           if ((p >= vStart) && (p < vEnd)) {
10066:             /* Old vertices stay the same */
10067:             newp = vStartNew + (p - vStart);
10068:             DMLabelSetValue(labelNew, newp, values[val]);
10069:           } else if ((p >= eStart) && (p < eEnd)) {
10070:             /* Old edges add new edges and vertex */
10071:             for (r = 0; r < 2; ++r) {
10072:               newp = eStartNew + (p - eStart)*2 + r;
10073:               DMLabelSetValue(labelNew, newp, values[val]);
10074:             }
10075:             newp = vStartNew + (vEnd - vStart) + (p - eStart);
10076:             DMLabelSetValue(labelNew, newp, values[val]);
10077:           } else if ((p >= fStart) && (p < fEnd)) {
10078:             /* Old faces add new faces, edges, and vertex */
10079:             for (r = 0; r < 4; ++r) {
10080:               newp = fStartNew + (p - fStart)*4 + r;
10081:               DMLabelSetValue(labelNew, newp, values[val]);
10082:             }
10083:             for (r = 0; r < 4; ++r) {
10084:               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*4 + r;
10085:               DMLabelSetValue(labelNew, newp, values[val]);
10086:             }
10087:             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (p - fStart);
10088:             DMLabelSetValue(labelNew, newp, values[val]);
10089:           } else if ((p >= cStart) && (p < cEnd)) {
10090:             /* Old cells add new cells, faces, edges, and vertex */
10091:             for (r = 0; r < 8; ++r) {
10092:               newp = cStartNew + (p - cStart)*8 + r;
10093:               DMLabelSetValue(labelNew, newp, values[val]);
10094:             }
10095:             for (r = 0; r < 12; ++r) {
10096:               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*12 + r;
10097:               DMLabelSetValue(labelNew, newp, values[val]);
10098:             }
10099:             for (r = 0; r < 6; ++r) {
10100:               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (p - cStart)*6 + r;
10101:               DMLabelSetValue(labelNew, newp, values[val]);
10102:             }
10103:             newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (p - cStart);
10104:             DMLabelSetValue(labelNew, newp, values[val]);
10105:           }
10106:           break;
10107:         case REFINER_HYBRID_HEX_3D:
10108:           if ((p >= vStart) && (p < vEnd)) {
10109:             /* Interior vertices stay the same */
10110:             newp = vStartNew + (p - vStart);
10111:             DMLabelSetValue(labelNew, newp, values[val]);
10112:           } else if ((p >= eStart) && (p < eMax)) {
10113:             /* Interior edges add new edges and vertex */
10114:             for (r = 0; r < 2; ++r) {
10115:               newp = eStartNew + (p - eStart)*2 + r;
10116:               DMLabelSetValue(labelNew, newp, values[val]);
10117:             }
10118:             newp = vStartNew + (vEnd - vStart) + (p - eStart);
10119:             DMLabelSetValue(labelNew, newp, values[val]);
10120:           } else if ((p >= eMax) && (p < eEnd)) {
10121:             /* Hybrid edges stay the same */
10122:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - eMax);
10123:             DMLabelSetValue(labelNew, newp, values[val]);
10124:           } else if ((p >= fStart) && (p < fMax)) {
10125:             /* Interior faces add new faces, edges, and vertex */
10126:             for (r = 0; r < 4; ++r) {
10127:               newp = fStartNew + (p - fStart)*4 + r;
10128:               DMLabelSetValue(labelNew, newp, values[val]);
10129:             }
10130:             for (r = 0; r < 4; ++r) {
10131:               newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*4 + r;
10132:               DMLabelSetValue(labelNew, newp, values[val]);
10133:             }
10134:             newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (p - fStart);
10135:             DMLabelSetValue(labelNew, newp, values[val]);
10136:           } else if ((p >= fMax) && (p < fEnd)) {
10137:             /* Hybrid faces add new faces and edges */
10138:             for (r = 0; r < 2; ++r) {
10139:               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (p - fMax)*2 + r;
10140:               DMLabelSetValue(labelNew, newp, values[val]);
10141:             }
10142:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - fMax);
10143:             DMLabelSetValue(labelNew, newp, values[val]);
10144:           } else if ((p >= cStart) && (p < cMax)) {
10145:             /* Interior cells add new cells, faces, edges, and vertex */
10146:             for (r = 0; r < 8; ++r) {
10147:               newp = cStartNew + (p - cStart)*8 + r;
10148:               DMLabelSetValue(labelNew, newp, values[val]);
10149:             }
10150:             for (r = 0; r < 12; ++r) {
10151:               newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*12 + r;
10152:               DMLabelSetValue(labelNew, newp, values[val]);
10153:             }
10154:             for (r = 0; r < 6; ++r) {
10155:               newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (p - cStart)*6 + r;
10156:               DMLabelSetValue(labelNew, newp, values[val]);
10157:             }
10158:             newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (p - cStart);
10159:             DMLabelSetValue(labelNew, newp, values[val]);
10160:           } else if ((p >= cMax) && (p < cEnd)) {
10161:             /* Hybrid cells add new cells, faces, and edges */
10162:             for (r = 0; r < 4; ++r) {
10163:               newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
10164:               DMLabelSetValue(labelNew, newp, values[val]);
10165:             }
10166:             for (r = 0; r < 4; ++r) {
10167:               newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (p - cMax)*4 + r;
10168:               DMLabelSetValue(labelNew, newp, values[val]);
10169:             }
10170:             newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (fEnd - fMax) + (p - cMax);
10171:             DMLabelSetValue(labelNew, newp, values[val]);
10172:           }
10173:           break;
10174:         default:
10175:           SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[refiner]);
10176:         }
10177:       }
10178:       ISRestoreIndices(pointIS, &points);
10179:       ISDestroy(&pointIS);
10180:     }
10181:     ISRestoreIndices(valueIS, &values);
10182:     ISDestroy(&valueIS);
10183:   }
10184:   return(0);
10185: }

10187: /* This will only work for interpolated meshes */
10188: PetscErrorCode DMPlexRefineUniform_Internal(DM dm, CellRefiner cellRefiner, DM *dmRefined)
10189: {
10190:   DM             rdm;
10191:   PetscInt      *depthSize;
10192:   PetscInt       dim, embedDim, depth = 0, d, pStart = 0, pEnd = 0;

10196:   DMCreate(PetscObjectComm((PetscObject)dm), &rdm);
10197:   DMSetType(rdm, DMPLEX);
10198:   DMGetDimension(dm, &dim);
10199:   DMSetDimension(rdm, dim);
10200:   DMGetCoordinateDim(dm, &embedDim);
10201:   DMSetCoordinateDim(rdm, embedDim);
10202:   /* Calculate number of new points of each depth */
10203:   DMPlexGetDepth(dm, &depth);
10204:   if (depth >= 0 && dim != depth) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated for regular refinement");
10205:   PetscMalloc1(depth+1, &depthSize);
10206:   PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));
10207:   CellRefinerGetSizes(cellRefiner, dm, depthSize);
10208:   /* Step 1: Set chart */
10209:   for (d = 0; d <= depth; ++d) pEnd += depthSize[d];
10210:   DMPlexSetChart(rdm, pStart, pEnd);
10211:   /* Step 2: Set cone/support sizes (automatically stratifies) */
10212:   CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);
10213:   /* Step 3: Setup refined DM */
10214:   DMSetUp(rdm);
10215:   /* Step 4: Set cones and supports (automatically symmetrizes) */
10216:   CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);
10217:   /* Step 5: Create pointSF */
10218:   CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);
10219:   /* Step 6: Create labels */
10220:   CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);
10221:   /* Step 7: Set coordinates */
10222:   CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);
10223:   PetscFree(depthSize);

10225:   *dmRefined = rdm;
10226:   return(0);
10227: }

10229: /*@
10230:   DMPlexCreateCoarsePointIS - Creates an IS covering the coarse DM chart with the fine points as data

10232:   Input Parameter:
10233: . dm - The coarse DM

10235:   Output Parameter:
10236: . fpointIS - The IS of all the fine points which exist in the original coarse mesh

10238:   Level: developer

10240: .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexCreateSubpointIS()
10241: @*/
10242: PetscErrorCode DMPlexCreateCoarsePointIS(DM dm, IS *fpointIS)
10243: {
10244:   CellRefiner    cellRefiner;
10245:   PetscInt      *depthSize, *fpoints;
10246:   PetscInt       cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
10247:   PetscInt       depth, pStart, pEnd, p, vStart, vEnd, v;

10251:   DMPlexGetDepth(dm, &depth);
10252:   DMPlexGetChart(dm, &pStart, &pEnd);
10253:   DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
10254:   DMPlexGetCellRefiner_Internal(dm, &cellRefiner);
10255:   PetscMalloc1(depth+1, &depthSize);
10256:   CellRefinerGetSizes(cellRefiner, dm, depthSize);
10257:   if (cellRefiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
10258:   PetscMalloc1(pEnd-pStart,&fpoints);
10259:   for (p = 0; p < pEnd-pStart; ++p) fpoints[p] = -1;
10260:   switch (cellRefiner) {
10261:   case REFINER_SIMPLEX_1D:
10262:   case REFINER_SIMPLEX_2D:
10263:   case REFINER_HYBRID_SIMPLEX_2D:
10264:   case REFINER_HEX_2D:
10265:   case REFINER_HYBRID_HEX_2D:
10266:   case REFINER_SIMPLEX_3D:
10267:   case REFINER_HYBRID_SIMPLEX_3D:
10268:   case REFINER_HEX_3D:
10269:   case REFINER_HYBRID_HEX_3D:
10270:     for (v = vStart; v < vEnd; ++v) fpoints[v-pStart] = vStartNew + (v - vStart);
10271:     break;
10272:   default:
10273:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %s", CellRefiners[cellRefiner]);
10274:   }
10275:   ISCreateGeneral(PETSC_COMM_SELF, pEnd-pStart, fpoints, PETSC_OWN_POINTER, fpointIS);
10276:   PetscFree(depthSize);
10277:   return(0);
10278: }

10280: /*@
10281:   DMPlexSetRefinementUniform - Set the flag for uniform refinement

10283:   Input Parameters:
10284: + dm - The DM
10285: - refinementUniform - The flag for uniform refinement

10287:   Level: developer

10289: .seealso: DMRefine(), DMPlexGetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
10290: @*/
10291: PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
10292: {
10293:   DM_Plex *mesh = (DM_Plex*) dm->data;

10297:   mesh->refinementUniform = refinementUniform;
10298:   return(0);
10299: }

10301: /*@
10302:   DMPlexGetRefinementUniform - Retrieve the flag for uniform refinement

10304:   Input Parameter:
10305: . dm - The DM

10307:   Output Parameter:
10308: . refinementUniform - The flag for uniform refinement

10310:   Level: developer

10312: .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
10313: @*/
10314: PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
10315: {
10316:   DM_Plex *mesh = (DM_Plex*) dm->data;

10321:   *refinementUniform = mesh->refinementUniform;
10322:   return(0);
10323: }

10325: /*@
10326:   DMPlexSetRefinementLimit - Set the maximum cell volume for refinement

10328:   Input Parameters:
10329: + dm - The DM
10330: - refinementLimit - The maximum cell volume in the refined mesh

10332:   Level: developer

10334: .seealso: DMRefine(), DMPlexGetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
10335: @*/
10336: PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
10337: {
10338:   DM_Plex *mesh = (DM_Plex*) dm->data;

10342:   mesh->refinementLimit = refinementLimit;
10343:   return(0);
10344: }

10346: /*@
10347:   DMPlexGetRefinementLimit - Retrieve the maximum cell volume for refinement

10349:   Input Parameter:
10350: . dm - The DM

10352:   Output Parameter:
10353: . refinementLimit - The maximum cell volume in the refined mesh

10355:   Level: developer

10357: .seealso: DMRefine(), DMPlexSetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
10358: @*/
10359: PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
10360: {
10361:   DM_Plex *mesh = (DM_Plex*) dm->data;

10366:   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
10367:   *refinementLimit = mesh->refinementLimit;
10368:   return(0);
10369: }

10371: /*@
10372:   DMPlexSetRefinementFunction - Set the function giving the maximum cell volume for refinement

10374:   Input Parameters:
10375: + dm - The DM
10376: - refinementFunc - Function giving the maximum cell volume in the refined mesh

10378:   Note: The calling sequence is refinementFunc(coords, limit)
10379: $ coords - Coordinates of the current point, usually a cell centroid
10380: $ limit  - The maximum cell volume for a cell containing this point

10382:   Level: developer

10384: .seealso: DMRefine(), DMPlexGetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
10385: @*/
10386: PetscErrorCode DMPlexSetRefinementFunction(DM dm, PetscErrorCode (*refinementFunc)(const PetscReal [], PetscReal *))
10387: {
10388:   DM_Plex *mesh = (DM_Plex*) dm->data;

10392:   mesh->refinementFunc = refinementFunc;
10393:   return(0);
10394: }

10396: /*@
10397:   DMPlexGetRefinementFunction - Get the function giving the maximum cell volume for refinement

10399:   Input Parameter:
10400: . dm - The DM

10402:   Output Parameter:
10403: . refinementFunc - Function giving the maximum cell volume in the refined mesh

10405:   Note: The calling sequence is refinementFunc(coords, limit)
10406: $ coords - Coordinates of the current point, usually a cell centroid
10407: $ limit  - The maximum cell volume for a cell containing this point

10409:   Level: developer

10411: .seealso: DMRefine(), DMPlexSetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
10412: @*/
10413: PetscErrorCode DMPlexGetRefinementFunction(DM dm, PetscErrorCode (**refinementFunc)(const PetscReal [], PetscReal *))
10414: {
10415:   DM_Plex *mesh = (DM_Plex*) dm->data;

10420:   *refinementFunc = mesh->refinementFunc;
10421:   return(0);
10422: }

10424: PetscErrorCode DMPlexGetCellRefiner_Internal(DM dm, CellRefiner *cellRefiner)
10425: {
10426:   PetscInt       dim, cStart, cEnd, coneSize, cMax, fMax;

10430:   DMGetDimension(dm, &dim);
10431:   DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
10432:   if (cEnd <= cStart) {*cellRefiner = REFINER_NOOP; return(0);}
10433:   DMPlexGetConeSize(dm, cStart, &coneSize);
10434:   DMPlexGetHybridBounds(dm, &cMax, &fMax, NULL, NULL);
10435:   switch (dim) {
10436:   case 1:
10437:     switch (coneSize) {
10438:     case 2:
10439:       *cellRefiner = REFINER_SIMPLEX_1D;
10440:       break;
10441:     default:
10442:       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %D in dimension %D for cell refiner", coneSize, dim);
10443:     }
10444:     break;
10445:   case 2:
10446:     switch (coneSize) {
10447:     case 3:
10448:       if (cMax >= 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_2D;
10449:       else *cellRefiner = REFINER_SIMPLEX_2D;
10450:       break;
10451:     case 4:
10452:       if (cMax >= 0 && fMax >= 0) *cellRefiner = REFINER_HYBRID_HEX_2D;
10453:       else *cellRefiner = REFINER_HEX_2D;
10454:       break;
10455:     default:
10456:       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %D in dimension %D for cell refiner", coneSize, dim);
10457:     }
10458:     break;
10459:   case 3:
10460:     switch (coneSize) {
10461:     case 4:
10462:       if (cMax >= 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_3D;
10463:       else *cellRefiner = REFINER_SIMPLEX_3D;
10464:       break;
10465:     case 5:
10466:       if (cMax == 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_3D;
10467:       else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %D in dimension %D for cell refiner", coneSize, dim);
10468:       break;
10469:     case 6:
10470:       if (cMax >= 0) *cellRefiner = REFINER_HYBRID_HEX_3D;
10471:       else *cellRefiner = REFINER_HEX_3D;
10472:       break;
10473:     default:
10474:       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %D in dimension %D for cell refiner", coneSize, dim);
10475:     }
10476:     break;
10477:   default:
10478:     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %D for cell refiner", dim);
10479:   }
10480:   return(0);
10481: }

10483: PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined)
10484: {
10485:   PetscBool      isUniform;

10489:   DMPlexGetRefinementUniform(dm, &isUniform);
10490:   if (isUniform) {
10491:     CellRefiner cellRefiner;
10492:     PetscBool   localized;

10494:     DMGetCoordinatesLocalized(dm, &localized);
10495:     DMPlexGetCellRefiner_Internal(dm, &cellRefiner);
10496:     DMPlexRefineUniform_Internal(dm, cellRefiner, dmRefined);
10497:     DMPlexSetRegularRefinement(*dmRefined, PETSC_TRUE);
10498:     DMCopyBoundary(dm, *dmRefined);
10499:     if (localized) {DMLocalizeCoordinates(*dmRefined);}
10500:   } else {
10501:     DMPlexRefine_Internal(dm, NULL, dmRefined);
10502:   }
10503:   return(0);
10504: }

10506: PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM dmRefined[])
10507: {
10508:   DM             cdm = dm;
10509:   PetscInt       r;
10510:   PetscBool      isUniform, localized;

10514:   DMPlexGetRefinementUniform(dm, &isUniform);
10515:   DMGetCoordinatesLocalized(dm, &localized);
10516:   if (isUniform) {
10517:     for (r = 0; r < nlevels; ++r) {
10518:       CellRefiner cellRefiner;

10520:       DMPlexGetCellRefiner_Internal(cdm, &cellRefiner);
10521:       DMPlexRefineUniform_Internal(cdm, cellRefiner, &dmRefined[r]);
10522:       DMSetCoarsenLevel(dmRefined[r], cdm->leveldown);
10523:       DMSetRefineLevel(dmRefined[r], cdm->levelup+1);
10524:       DMCopyBoundary(cdm, dmRefined[r]);
10525:       if (localized) {DMLocalizeCoordinates(dmRefined[r]);}
10526:       DMSetCoarseDM(dmRefined[r], cdm);
10527:       DMPlexSetRegularRefinement(dmRefined[r], PETSC_TRUE);
10528:       cdm  = dmRefined[r];
10529:     }
10530:   } else {
10531:     for (r = 0; r < nlevels; ++r) {
10532:       DMRefine(cdm, PetscObjectComm((PetscObject) dm), &dmRefined[r]);
10533:       DMCopyBoundary(cdm, dmRefined[r]);
10534:       if (localized) {DMLocalizeCoordinates(dmRefined[r]);}
10535:       DMSetCoarseDM(dmRefined[r], cdm);
10536:       cdm  = dmRefined[r];
10537:     }
10538:   }
10539:   return(0);
10540: }