Actual source code: plexrefregular.c

  1: #include <petsc/private/dmplextransformimpl.h>

  3: /*
  4:    Regular Refinement of Hybrid Meshes

  6:    We would like to express regular refinement as a small set of rules that can be applied on every point of the Plex
  7:    to automatically generate a refined Plex. In fact, we would like these rules to be general enough to encompass other
  8:    transformations, such as changing from one type of cell to another, as simplex to hex.

 10:    To start, we can create a function that takes an original cell type and returns the number of new cells replacing it
 11:    and the types of the new cells.

 13:    We need the group multiplication table for group actions from the dihedral group for each cell type.

 15:    We need an operator which takes in a cell, and produces a new set of cells with new faces and correct orientations. I think
 16:    we can just write this operator for faces with identity, and then compose the face orientation actions to get the actual
 17:    (face, orient) pairs for each subcell.
 18: */

 20: /*@
 21:   DMPlexRefineRegularGetAffineFaceTransforms - Gets the affine map from the reference face cell to each face in the given cell

 23:   Input Parameters:
 24: + tr - The `DMPlexTransform` object
 25: - ct - The cell type

 27:   Output Parameters:
 28: + Nf   - The number of faces for this cell type
 29: . v0   - The translation of the first vertex for each face
 30: . J    - The Jacobian for each face (map from original cell to subcell)
 31: . invJ - The inverse Jacobian for each face
 32: - detJ - The determinant of the Jacobian for each face

 34:   Level: developer

 36:   Note:
 37:   The Jacobian and inverse Jacobian will be rectangular, and the inverse is really a generalized inverse.
 38: .vb
 39:     v0 + j x_face = x_cell
 40:     invj (x_cell - v0) = x_face
 41: .ve

 43: .seealso: `DMPLEX`, `DM`, `DMPlexTransform`, `DMPolytopeType`, `DMPlexCellRefinerGetAffineTransforms()`
 44: @*/
 45: PetscErrorCode DMPlexRefineRegularGetAffineFaceTransforms(DMPlexTransform tr, DMPolytopeType ct, PetscInt *Nf, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[], PetscReal *detJ[])
 46: {
 47:   /*
 48:    2
 49:    |\
 50:    | \
 51:    |  \
 52:    |   \
 53:    |    \
 54:    |     \
 55:    |      \
 56:    2       1
 57:    |        \
 58:    |         \
 59:    |          \
 60:    0---0-------1
 61:    v0[Nf][dc]:       3 x 2
 62:    J[Nf][df][dc]:    3 x 1 x 2
 63:    invJ[Nf][dc][df]: 3 x 2 x 1
 64:    detJ[Nf]:         3
 65:    */
 66:   static PetscReal tri_v0[]   = {0.0, -1.0, 0.0, 0.0, -1.0, 0.0};
 67:   static PetscReal tri_J[]    = {1.0, 0.0, -1.0, 1.0, 0.0, -1.0};
 68:   static PetscReal tri_invJ[] = {1.0, 0.0, -0.5, 0.5, 0.0, -1.0};
 69:   static PetscReal tri_detJ[] = {1.0, 1.414213562373095, 1.0};
 70:   /*
 71:    3---------2---------2
 72:    |                   |
 73:    |                   |
 74:    |                   |
 75:    3                   1
 76:    |                   |
 77:    |                   |
 78:    |                   |
 79:    0---------0---------1

 81:    v0[Nf][dc]:       4 x 2
 82:    J[Nf][df][dc]:    4 x 1 x 2
 83:    invJ[Nf][dc][df]: 4 x 2 x 1
 84:    detJ[Nf]:         4
 85:    */
 86:   static PetscReal quad_v0[]   = {0.0, -1.0, 1.0, 0.0, 0.0, 1.0, -1.0, 0.0};
 87:   static PetscReal quad_J[]    = {1.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0, -1.0};
 88:   static PetscReal quad_invJ[] = {1.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0, -1.0};
 89:   static PetscReal quad_detJ[] = {1.0, 1.0, 1.0, 1.0};

 91:   PetscFunctionBegin;
 92:   switch (ct) {
 93:   case DM_POLYTOPE_TRIANGLE:
 94:     if (Nf) *Nf = 3;
 95:     if (v0) *v0 = tri_v0;
 96:     if (J) *J = tri_J;
 97:     if (invJ) *invJ = tri_invJ;
 98:     if (detJ) *detJ = tri_detJ;
 99:     break;
100:   case DM_POLYTOPE_QUADRILATERAL:
101:     if (Nf) *Nf = 4;
102:     if (v0) *v0 = quad_v0;
103:     if (J) *J = quad_J;
104:     if (invJ) *invJ = quad_invJ;
105:     if (detJ) *detJ = quad_detJ;
106:     break;
107:   default:
108:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
109:   }
110:   PetscFunctionReturn(PETSC_SUCCESS);
111: }

113: /*@
114:   DMPlexRefineRegularGetAffineTransforms - Gets the affine map from the reference cell to each subcell

116:   Input Parameters:
117: + tr - The `DMPlexTransform` object
118: - ct - The cell type

120:   Output Parameters:
121: + Nc   - The number of subcells produced from this cell type
122: . v0   - The translation of the first vertex for each subcell, an array of length $dim * Nc$. Pass `NULL` to ignore.
123: . J    - The Jacobian for each subcell (map from reference cell to subcell), an array of length $dim^2 * Nc$. Pass `NULL` to ignore.
124: - invJ - The inverse Jacobian for each subcell, an array of length $dim^2 * Nc$. Pass `NULL` to ignore.

126:   Level: developer

128:   Note:
129:   Do not free these output arrays

131: .seealso: `DMPLEX`, `DM`, `DMPlexTransform`, `DMPolytopeType`, `DMPlexRefineRegularGetAffineFaceTransforms()`, `DMPLEXREFINEREGULAR`
132: @*/
133: PetscErrorCode DMPlexRefineRegularGetAffineTransforms(DMPlexTransform tr, DMPolytopeType ct, PetscInt *Nc, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[])
134: {
135:   /* 0--A--0--B--1 */
136:   static PetscReal seg_v0[]   = {-1.0, 0.0};
137:   static PetscReal seg_J[]    = {0.5, 0.5};
138:   static PetscReal seg_invJ[] = {2.0, 2.0};
139:   /*
140:    2
141:    |\
142:    | \
143:    |  \
144:    |   \
145:    | C  \
146:    |     \
147:    |      \
148:    2---1---1
149:    |\  D  / \
150:    | 2   0   \
151:    |A \ /  B  \
152:    0---0-------1
153:    */
154:   static PetscReal tri_v0[]   = {-1.0, -1.0, 0.0, -1.0, -1.0, 0.0, 0.0, -1.0};
155:   static PetscReal tri_J[]    = {0.5, 0.0,  0.0, 0.5,

157:                                  0.5, 0.0,  0.0, 0.5,

159:                                  0.5, 0.0,  0.0, 0.5,

161:                                  0.0, -0.5, 0.5, 0.5};
162:   static PetscReal tri_invJ[] = {2.0, 0.0, 0.0,  2.0,

164:                                  2.0, 0.0, 0.0,  2.0,

166:                                  2.0, 0.0, 0.0,  2.0,

168:                                  2.0, 2.0, -2.0, 0.0};
169:   static PetscReal tet_v0[]   = {-1.0, -1.0, -1.0, -1.0, 0.0, -1.0, 0.0, -1.0, -1.0, -1.0, -1.0, 0.0, 0.0, -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0};
170:   static PetscReal tet_J[]    = {0.5,  0.0,  0.0,  0.0, 0.5, 0.0,  0.0,  0.0,  0.5,

172:                                  0.5,  0.0,  0.0,  0.0, 0.5, 0.0,  0.0,  0.0,  0.5,

174:                                  0.5,  0.0,  0.0,  0.0, 0.5, 0.0,  0.0,  0.0,  0.5,

176:                                  0.5,  0.0,  0.0,  0.0, 0.5, 0.0,  0.0,  0.0,  0.5,

178:                                  -0.5, -0.5, 0.0,  0.5, 0.0, 0.0,  0.0,  0.5,  0.5,

180:                                  0.0,  0.5,  0.5,  0.0, 0.0, -0.5, -0.5, -0.5, 0.0,

182:                                  -0.5, 0.0,  0.0,  0.5, 0.0, 0.5,  -0.5, -0.5, -0.5,

184:                                  -0.5, -0.5, -0.5, 0.5, 0.5, 0.0,  0.0,  -0.5, 0.0};
185:   static PetscReal tet_invJ[] = {2.0,  0.0,  0.0,  0.0,  2.0,  0.0,  0.0,  0.0,  2.0,

187:                                  2.0,  0.0,  0.0,  0.0,  2.0,  0.0,  0.0,  0.0,  2.0,

189:                                  2.0,  0.0,  0.0,  0.0,  2.0,  0.0,  0.0,  0.0,  2.0,

191:                                  2.0,  0.0,  0.0,  0.0,  2.0,  0.0,  0.0,  0.0,  2.0,

193:                                  0.0,  2.0,  0.0,  -2.0, -2.0, 0.0,  2.0,  2.0,  2.0,

195:                                  -2.0, -2.0, -2.0, 2.0,  2.0,  0.0,  0.0,  -2.0, 0.0,

197:                                  -2.0, 0.0,  0.0,  0.0,  -2.0, -2.0, 2.0,  2.0,  0.0,

199:                                  0.0,  2.0,  2.0,  0.0,  0.0,  -2.0, -2.0, -2.0, 0.0};
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:   static PetscReal quad_v0[]   = {-1.0, -1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0};
212:   static PetscReal quad_J[]    = {0.5, 0.0, 0.0, 0.5,

214:                                   0.5, 0.0, 0.0, 0.5,

216:                                   0.5, 0.0, 0.0, 0.5,

218:                                   0.5, 0.0, 0.0, 0.5};
219:   static PetscReal quad_invJ[] = {2.0, 0.0, 0.0, 2.0,

221:                                   2.0, 0.0, 0.0, 2.0,

223:                                   2.0, 0.0, 0.0, 2.0,

225:                                   2.0, 0.0, 0.0, 2.0};
226:   /*
227:      Bottom (viewed from top)    Top
228:      1---------2---------2       7---------2---------6
229:      |         |         |       |         |         |
230:      |    B    2    C    |       |    H    2    G    |
231:      |         |         |       |         |         |
232:      3----3----0----1----1       3----3----0----1----1
233:      |         |         |       |         |         |
234:      |    A    0    D    |       |    E    0    F    |
235:      |         |         |       |         |         |
236:      0---------0---------3       4---------0---------5
237:      */
238:   static PetscReal hex_v0[]   = {-1.0, -1.0, -1.0, -1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, -1.0, -1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0};
239:   static PetscReal hex_J[]    = {0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5,

241:                                  0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5,

243:                                  0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5,

245:                                  0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5,

247:                                  0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5,

249:                                  0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5,

251:                                  0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5,

253:                                  0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5};
254:   static PetscReal hex_invJ[] = {2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0,

256:                                  2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0,

258:                                  2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0,

260:                                  2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0,

262:                                  2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0,

264:                                  2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0,

266:                                  2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0,

268:                                  2.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0};

270:   PetscFunctionBegin;
271:   switch (ct) {
272:   case DM_POLYTOPE_SEGMENT:
273:     if (Nc) *Nc = 2;
274:     if (v0) *v0 = seg_v0;
275:     if (J) *J = seg_J;
276:     if (invJ) *invJ = seg_invJ;
277:     break;
278:   case DM_POLYTOPE_TRIANGLE:
279:     if (Nc) *Nc = 4;
280:     if (v0) *v0 = tri_v0;
281:     if (J) *J = tri_J;
282:     if (invJ) *invJ = tri_invJ;
283:     break;
284:   case DM_POLYTOPE_QUADRILATERAL:
285:     if (Nc) *Nc = 4;
286:     if (v0) *v0 = quad_v0;
287:     if (J) *J = quad_J;
288:     if (invJ) *invJ = quad_invJ;
289:     break;
290:   case DM_POLYTOPE_TETRAHEDRON:
291:     if (Nc) *Nc = 8;
292:     if (v0) *v0 = tet_v0;
293:     if (J) *J = tet_J;
294:     if (invJ) *invJ = tet_invJ;
295:     break;
296:   case DM_POLYTOPE_HEXAHEDRON:
297:     if (Nc) *Nc = 8;
298:     if (v0) *v0 = hex_v0;
299:     if (J) *J = hex_J;
300:     if (invJ) *invJ = hex_invJ;
301:     break;
302:   default:
303:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
304:   }
305:   PetscFunctionReturn(PETSC_SUCCESS);
306: }

308: #if 0
309: static PetscErrorCode DMPlexCellRefinerGetCellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
310: {
311:   static PetscReal seg_v[]  = {-1.0,  0.0,  1.0};
312:   static PetscReal tri_v[]  = {-1.0, -1.0,  1.0, -1.0,  -1.0, 1.0,  0.0, -1.0,  0.0, 0.0,  -1.0, 0.0};
313:   static PetscReal quad_v[] = {-1.0, -1.0,  1.0, -1.0,   1.0, 1.0,  -1.0, 1.0,  0.0, -1.0,  1.0, 0.0,   0.0, 1.0,  -1.0, 0.0,  0.0, 0.0};
314:   static PetscReal tet_v[]  = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
315:                                -1.0,  0.0, -1.0,   0.0,  0.0, -1.0,  -1.0,  1.0, -1.0,
316:                                -1.0, -1.0,  0.0,   0.0, -1.0,  0.0,  -1.0,  0.0,  0.0,  -1.0, -1.0,  1.0};
317:   static PetscReal hex_v[]  = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
318:                                -1.0,  0.0, -1.0,   0.0,  0.0, -1.0,   1.0,  0.0, -1.0,
319:                                -1.0,  1.0, -1.0,   0.0,  1.0, -1.0,   1.0,  1.0, -1.0,
320:                                -1.0, -1.0,  0.0,   0.0, -1.0,  0.0,   1.0, -1.0,  0.0,
321:                                -1.0,  0.0,  0.0,   0.0,  0.0,  0.0,   1.0,  0.0,  0.0,
322:                                -1.0,  1.0,  0.0,   0.0,  1.0,  0.0,   1.0,  1.0,  0.0,
323:                                -1.0, -1.0,  1.0,   0.0, -1.0,  1.0,   1.0, -1.0,  1.0,
324:                                -1.0,  0.0,  1.0,   0.0,  0.0,  1.0,   1.0,  0.0,  1.0,
325:                                -1.0,  1.0,  1.0,   0.0,  1.0,  1.0,   1.0,  1.0,  1.0};

327:   PetscFunctionBegin;
328:   switch (ct) {
329:     case DM_POLYTOPE_SEGMENT:       *Nv =  3; *subcellV = seg_v;  break;
330:     case DM_POLYTOPE_TRIANGLE:      *Nv =  6; *subcellV = tri_v;  break;
331:     case DM_POLYTOPE_QUADRILATERAL: *Nv =  9; *subcellV = quad_v; break;
332:     case DM_POLYTOPE_TETRAHEDRON:   *Nv = 10; *subcellV = tet_v;  break;
333:     case DM_POLYTOPE_HEXAHEDRON:    *Nv = 27; *subcellV = hex_v;  break;
334:     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
335:   }
336:   PetscFunctionReturn(PETSC_SUCCESS);
337: }

339: static PetscErrorCode DMPlexCellRefinerGetSubcellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
340: {
341:   static PetscInt seg_v[]  = {0, 1, 1, 2};
342:   static PetscInt tri_v[]  = {0, 3, 5,  3, 1, 4,  5, 4, 2,  3, 4, 5};
343:   static PetscInt quad_v[] = {0, 4, 8, 7,  4, 1, 5, 8,  8, 5, 2, 6,  7, 8, 6, 3};
344:   static PetscInt tet_v[]  = {0, 3, 1, 6,  3, 2, 4, 8,  1, 4, 5, 7,  6, 8, 7, 9,
345:                               1, 6, 3, 7,  8, 4, 3, 7,  7, 3, 1, 4,  7, 3, 8, 6};
346:   static PetscInt hex_v[]  = {0,  3,  4,  1,  9, 10, 13, 12,   3,  6,  7,  4, 12, 13, 16, 15,   4,  7,  8,  5, 13, 14, 17, 16,   1,  4 , 5 , 2, 10, 11, 14, 13,
347:                               9, 12, 13, 10, 18, 19, 22, 21,  10, 13, 14, 11, 19, 20, 23, 22,  13, 16, 17, 14, 22, 23, 26, 25,  12, 15, 16, 13, 21, 22, 25, 24};

349:   PetscFunctionBegin;
350:   PetscCheck(ct == rct,PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]);
351:   switch (ct) {
352:     case DM_POLYTOPE_SEGMENT:       *Nv = 2; *subcellV = &seg_v[r*(*Nv)];  break;
353:     case DM_POLYTOPE_TRIANGLE:      *Nv = 3; *subcellV = &tri_v[r*(*Nv)];  break;
354:     case DM_POLYTOPE_QUADRILATERAL: *Nv = 4; *subcellV = &quad_v[r*(*Nv)]; break;
355:     case DM_POLYTOPE_TETRAHEDRON:   *Nv = 4; *subcellV = &tet_v[r*(*Nv)];  break;
356:     case DM_POLYTOPE_HEXAHEDRON:    *Nv = 8; *subcellV = &hex_v[r*(*Nv)];  break;
357:     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
358:   }
359:   PetscFunctionReturn(PETSC_SUCCESS);
360: }
361: #endif

363: static PetscErrorCode DMPlexTransformView_Regular(DMPlexTransform tr, PetscViewer viewer)
364: {
365:   PetscBool isascii;

367:   PetscFunctionBegin;
370:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
371:   if (isascii) {
372:     const char *name;

374:     PetscCall(PetscObjectGetName((PetscObject)tr, &name));
375:     PetscCall(PetscViewerASCIIPrintf(viewer, "Regular refinement %s\n", name ? name : ""));
376:   } else {
377:     SETERRQ(PetscObjectComm((PetscObject)tr), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlexTransform writing", ((PetscObject)viewer)->type_name);
378:   }
379:   PetscFunctionReturn(PETSC_SUCCESS);
380: }

382: static PetscErrorCode DMPlexTransformSetUp_Regular(DMPlexTransform tr)
383: {
384:   PetscFunctionBegin;
385:   PetscFunctionReturn(PETSC_SUCCESS);
386: }

388: static PetscErrorCode DMPlexTransformDestroy_Regular(DMPlexTransform tr)
389: {
390:   DMPlexRefine_Regular *f = (DMPlexRefine_Regular *)tr->data;

392:   PetscFunctionBegin;
393:   PetscCall(PetscFree(f));
394:   PetscFunctionReturn(PETSC_SUCCESS);
395: }

397: PetscErrorCode DMPlexTransformGetSubcellOrientation_Regular(DMPlexTransform tr, DMPolytopeType sct, PetscInt sp, PetscInt so, DMPolytopeType tct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
398: {
399:   static PetscInt seg_seg[]   = {1, -1, 0, -1, 0, 0, 1, 0};
400:   static PetscInt tri_seg[]   = {2, -1, 1, -1, 0, -1, 1, -1, 0, -1, 2, -1, 0, -1, 2, -1, 1, -1, 0, 0, 1, 0, 2, 0, 1, 0, 2, 0, 0, 0, 2, 0, 0, 0, 1, 0};
401:   static PetscInt tri_tri[]   = {1, -3, 0, -3, 2, -3, 3, -2, 0, -2, 2, -2, 1, -2, 3, -1, 2, -1, 1, -1, 0, -1, 3, -3, 0, 0, 1, 0, 2, 0, 3, 0, 1, 1, 2, 1, 0, 1, 3, 1, 2, 2, 0, 2, 1, 2, 3, 2};
402:   static PetscInt quad_seg[]  = {1, 0, 0, 0, 3, 0, 2, 0, 0, 0, 3, 0, 2, 0, 1, 0, 3, 0, 2, 0, 1, 0, 0, 0, 2, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 2, 0, 3, 0, 1, 0, 2, 0, 3, 0, 0, 0, 2, 0, 3, 0, 0, 0, 1, 0, 3, 0, 0, 0, 1, 0, 2, 0};
403:   static PetscInt quad_quad[] = {2, -4, 1, -4, 0, -4, 3, -4, 1, -3, 0, -3, 3, -3, 2, -3, 0, -2, 3, -2, 2, -2, 1, -2, 3, -1, 2, -1, 1, -1, 0, -1, 0, 0, 1, 0, 2, 0, 3, 0, 1, 1, 2, 1, 3, 1, 0, 1, 2, 2, 3, 2, 0, 2, 1, 2, 3, 3, 0, 3, 1, 3, 2, 3};
404:   static PetscInt tseg_seg[]  = {0, -1, 0, 0, 0, 0, 0, -1};
405:   static PetscInt tseg_tseg[] = {1, -2, 0, -2, 1, -1, 0, -1, 0, 0, 1, 0, 0, 1, 1, 1};
406:   static PetscInt tet_seg[]   = {0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0};
407:   static PetscInt tet_tri[] = {2, -1, 3, -1, 1, -3, 0, -2, 6, 1, 7, -3, 5, 2, 4, -3, 3, -1, 1, -1, 2, -3, 0, -1, 4, 0,  5, 0,  6, 0,  7, 0,  1, -1, 2, -1, 3, -3, 0, -3, 4, 0,  5, 0,  6, 0,  7, 0, 3, -2, 2, -3, 0, -1, 1, -1, 7, -3, 6, 1, 4, 2,  5, -3,
408:                                2, -3, 0, -2, 3, -1, 1, -3, 4, 0, 5, 0,  6, 0, 7, 0,  0, -2, 3, -2, 2, -2, 1, -2, 4, 0,  5, 0,  6, 0,  7, 0,  0, -1, 1, -2, 3, -2, 2, -2, 7, 1,  6, -3, 5, -3, 4, 2, 1, -2, 3, -3, 0, -3, 2, -1, 4, 0,  5, 0, 6, 0,  7, 0,
409:                                3, -3, 0, -1, 1, -1, 2, -3, 4, 0, 5, 0,  6, 0, 7, 0,  1, -3, 0, -3, 2, -1, 3, -3, 6, -3, 7, 1,  4, -3, 5, 2,  0, -3, 2, -2, 1, -2, 3, -2, 4, 0,  5, 0,  6, 0,  7, 0, 2, -2, 1, -3, 0, -2, 3, -1, 4, 0,  5, 0, 6, 0,  7, 0,
410:                                0, 0,  1, 0,  2, 0,  3, 0,  4, 0, 5, 0,  6, 0, 7, 0,  1, 0,  2, 2,  0, 1,  3, 1,  4, 0,  5, 0,  6, 0,  7, 0,  2, 2,  0, 0,  1, 1,  3, 2,  4, 0,  5, 0,  6, 0,  7, 0, 1, 2,  0, 1,  3, 1,  2, 2,  5, 0,  4, 0, 7, -1, 6, -1,
411:                                0, 1,  3, 0,  1, 0,  2, 0,  4, 0, 5, 0,  6, 0, 7, 0,  3, 0,  1, 2,  0, 2,  2, 1,  4, 0,  5, 0,  6, 0,  7, 0,  2, 0,  3, 2,  0, 0,  1, 1,  4, -2, 5, -2, 7, 0,  6, 0, 3, 2,  0, 2,  2, 1,  1, 2,  4, 0,  5, 0, 6, 0,  7, 0,
412:                                0, 2,  2, 0,  3, 0,  1, 0,  4, 0, 5, 0,  6, 0, 7, 0,  3, 1,  2, 1,  1, 2,  0, 2,  5, -2, 4, -2, 6, -1, 7, -1, 2, 1,  1, 1,  3, 2,  0, 0,  4, 0,  5, 0,  6, 0,  7, 0, 1, 1,  3, 1,  2, 2,  0, 1,  4, 0,  5, 0, 6, 0,  7, 0};
413:   static PetscInt tet_tet[] = {2, -12, 3, -12, 1, -12, 0, -12, 6, -9, 7, -9, 5, -12, 4, -12, 3, -11, 1, -11, 2, -11, 0, -11, 4, 0,  5, 0,  6, 0,  7, 0,  1, -10, 2, -10, 3, -10, 0, -10, 4, 0,  5, 0,  6, 0,  7, 0,  3, -9, 2, -9, 0, -9, 1, -9,
414:                                7, -9,  6, -9,  4, -12, 5, -12, 2, -8, 0, -8, 3, -8,  1, -8,  4, 0,   5, 0,   6, 0,   7, 0,   0, -7, 3, -7, 2, -7, 1, -7, 4, 0,   5, 0,   6, 0,   7, 0,   0, -6, 1, -6, 3, -6, 2, -6, 4, -3, 5, -3, 7, -6, 6, -6,
415:                                1, -5,  3, -5,  0, -5,  2, -5,  4, 0,  5, 0,  6, 0,   7, 0,   3, -4,  0, -4,  1, -4,  2, -4,  4, 0,  5, 0,  6, 0,  7, 0,  1, -3,  0, -3,  2, -3,  3, -3,  5, -3, 4, -3, 6, -6, 7, -6, 0, -2, 2, -2, 1, -2, 3, -2,
416:                                4, 0,   5, 0,   6, 0,   7, 0,   2, -1, 1, -1, 0, -1,  3, -1,  4, 0,   5, 0,   6, 0,   7, 0,   0, 0,  1, 0,  2, 0,  3, 0,  4, 0,   5, 0,   6, 0,   7, 0,   1, 1,  2, 1,  0, 1,  3, 1,  4, 0,  5, 0,  6, 0,  7, 0,
417:                                2, 2,   0, 2,   1, 2,   3, 2,   4, 0,  5, 0,  6, 0,   7, 0,   1, 3,   0, 3,   3, 3,   2, 3,   5, 0,  4, 0,  7, 0,  6, 0,  0, 4,   3, 4,   1, 4,   2, 4,   4, 0,  5, 0,  6, 0,  7, 0,  3, 5,  1, 5,  0, 5,  2, 5,
418:                                4, 0,   5, 0,   6, 0,   7, 0,   2, 6,  3, 6,  0, 6,   1, 6,   6, 6,   7, 6,   4, 6,   5, 6,   3, 7,  0, 7,  2, 7,  1, 7,  4, 0,   5, 0,   6, 0,   7, 0,   0, 8,  2, 8,  3, 8,  1, 8,  4, 0,  5, 0,  6, 0,  7, 0,
419:                                3, 9,   2, 9,   1, 9,   0, 9,   7, 6,  6, 6,  5, 6,   4, 6,   2, 10,  1, 10,  3, 10,  0, 10,  4, 0,  5, 0,  6, 0,  7, 0,  1, 11,  3, 11,  2, 11,  0, 11,  4, 0,  5, 0,  6, 0,  7, 0};
420:   static PetscInt hex_seg[] = {2, 0, 3, 0, 4, 0, 5, 0, 1, 0, 0, 0, 4, 0, 5, 0, 0, 0, 1, 0, 3, 0, 2, 0, 5, 0, 4, 0, 1, 0, 0, 0, 3, 0, 2, 0, 3, 0, 2, 0, 4, 0, 5, 0, 0, 0, 1, 0, 3, 0, 2, 0, 5, 0, 4, 0, 1, 0, 0, 0, 4, 0, 5, 0, 1, 0, 0, 0, 2, 0, 3, 0,
421:                                2, 0, 3, 0, 5, 0, 4, 0, 0, 0, 1, 0, 5, 0, 4, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 3, 0, 2, 0, 1, 0, 0, 0, 5, 0, 4, 0, 3, 0, 2, 0, 0, 0, 1, 0, 3, 0, 2, 0, 1, 0, 0, 0, 4, 0, 5, 0, 2, 0, 3, 0, 0, 0, 1, 0, 4, 0, 5, 0,
422:                                1, 0, 0, 0, 4, 0, 5, 0, 3, 0, 2, 0, 1, 0, 0, 0, 5, 0, 4, 0, 2, 0, 3, 0, 5, 0, 4, 0, 2, 0, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 0, 4, 0, 5, 0, 4, 0, 5, 0, 2, 0, 3, 0, 0, 0, 1, 0, 3, 0, 2, 0, 0, 0, 1, 0, 5, 0, 4, 0,
423:                                1, 0, 0, 0, 3, 0, 2, 0, 5, 0, 4, 0, 2, 0, 3, 0, 1, 0, 0, 0, 5, 0, 4, 0, 0, 0, 1, 0, 4, 0, 5, 0, 2, 0, 3, 0, 0, 0, 1, 0, 3, 0, 2, 0, 4, 0, 5, 0, 0, 0, 1, 0, 5, 0, 4, 0, 3, 0, 2, 0, 0, 0, 1, 0, 2, 0, 3, 0, 5, 0, 4, 0,
424:                                0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 0, 0, 1, 0, 5, 0, 4, 0, 2, 0, 3, 0, 0, 0, 1, 0, 3, 0, 2, 0, 5, 0, 4, 0, 0, 0, 1, 0, 4, 0, 5, 0, 3, 0, 2, 0, 2, 0, 3, 0, 1, 0, 0, 0, 4, 0, 5, 0, 1, 0, 0, 0, 3, 0, 2, 0, 4, 0, 5, 0,
425:                                3, 0, 2, 0, 0, 0, 1, 0, 4, 0, 5, 0, 4, 0, 5, 0, 2, 0, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 0, 5, 0, 4, 0, 5, 0, 4, 0, 2, 0, 3, 0, 0, 0, 1, 0, 1, 0, 0, 0, 5, 0, 4, 0, 3, 0, 2, 0, 1, 0, 0, 0, 4, 0, 5, 0, 2, 0, 3, 0,
426:                                2, 0, 3, 0, 0, 0, 1, 0, 5, 0, 4, 0, 3, 0, 2, 0, 1, 0, 0, 0, 5, 0, 4, 0, 5, 0, 4, 0, 3, 0, 2, 0, 1, 0, 0, 0, 4, 0, 5, 0, 3, 0, 2, 0, 0, 0, 1, 0, 5, 0, 4, 0, 0, 0, 1, 0, 3, 0, 2, 0, 2, 0, 3, 0, 5, 0, 4, 0, 1, 0, 0, 0,
427:                                4, 0, 5, 0, 1, 0, 0, 0, 3, 0, 2, 0, 3, 0, 2, 0, 5, 0, 4, 0, 0, 0, 1, 0, 3, 0, 2, 0, 4, 0, 5, 0, 1, 0, 0, 0, 5, 0, 4, 0, 1, 0, 0, 0, 2, 0, 3, 0, 4, 0, 5, 0, 0, 0, 1, 0, 2, 0, 3, 0, 2, 0, 3, 0, 4, 0, 5, 0, 0, 0, 1, 0};
428:   static PetscInt hex_quad[]    = {7,  -2, 4,  -2, 5,  -2, 6,  -2, 8,  -3, 11, -3, 10, -3, 9,  -3, 3,  1,  2,  1,  1,  1,  0,  1,  8,  -2, 9,  -2, 10, -2, 11, -2, 3,  -4, 0,  -4, 1,  -4, 2,  -4, 7,  0,  4,  0,  5,  0,  6,  0,  9,  1,  8,  1,  11,
429:                                    1,  10, 1,  0,  3,  3,  3,  2,  3,  1,  3,  5,  2,  6,  2,  7,  2,  4,  2,  6,  3,  5,  3,  4,  3,  7,  3,  10, -1, 9,  -1, 8,  -1, 11, -1, 2,  -4, 3,  -4, 0,  -4, 1,  -4, 4,  1,  7,  1,  6,  1,  5,  1,  11, 2,
430:                                    8,  2,  9,  2,  10, 2,  1,  3,  0,  3,  3,  3,  2,  3,  10, -4, 11, -4, 8,  -4, 9,  -4, 2,  1,  1,  1,  0,  1,  3,  1,  6,  -1, 5,  -1, 4,  -1, 7,  -1, 5,  -4, 6,  -4, 7,  -4, 4,  -4, 9,  0,  10, 0,  11, 0,  8,
431:                                    0,  0,  -2, 1,  -2, 2,  -2, 3,  -2, 11, 3,  10, 3,  9,  3,  8,  3,  1,  -2, 2,  -2, 3,  -2, 0,  -2, 4,  -3, 7,  -3, 6,  -3, 5,  -3, 11, -1, 8,  -1, 9,  -1, 10, -1, 7,  3,  4,  3,  5,  3,  6,  3,  2,  2,  1,  2,
432:                                    0,  2,  3,  2,  10, 2,  9,  2,  8,  2,  11, 2,  5,  1,  6,  1,  7,  1,  4,  1,  1,  -1, 2,  -1, 3,  -1, 0,  -1, 5,  2,  4,  2,  7,  2,  6,  2,  1,  2,  0,  2,  3,  2,  2,  2,  10, -4, 9,  -4, 8,  -4, 11, -4, 4,
433:                                    -3, 5,  -3, 6,  -3, 7,  -3, 0,  -3, 1,  -3, 2,  -3, 3,  -3, 8,  -2, 11, -2, 10, -2, 9,  -2, 3,  1,  0,  1,  1,  1,  2,  1,  9,  -4, 8,  -4, 11, -4, 10, -4, 6,  3,  7,  3,  4,  3,  5,  3,  1,  3,  2,  3,  3,  3,
434:                                    0,  3,  10, 1,  11, 1,  8,  1,  9,  1,  5,  -4, 4,  -4, 7,  -4, 6,  -4, 8,  0,  11, 0,  10, 0,  9,  0,  4,  -4, 7,  -4, 6,  -4, 5,  -4, 0,  0,  3,  0,  2,  0,  1,  0,  0,  0,  1,  0,  2,  0,  3,  0,  5,  -1, 4,
435:                                    -1, 7,  -1, 6,  -1, 9,  -3, 8,  -3, 11, -3, 10, -3, 9,  -3, 10, -3, 11, -3, 8,  -3, 6,  -2, 5,  -2, 4,  -2, 7,  -2, 3,  -3, 0,  -3, 1,  -3, 2,  -3, 7,  0,  6,  0,  5,  0,  4,  0,  2,  -1, 3,  -1, 0,  -1, 1,  -1,
436:                                    11, 3,  8,  3,  9,  3,  10, 3,  2,  2,  3,  2,  0,  2,  1,  2,  6,  2,  7,  2,  4,  2,  5,  2,  10, 2,  11, 2,  8,  2,  9,  2,  6,  -1, 7,  -1, 4,  -1, 5,  -1, 3,  0,  2,  0,  1,  0,  0,  0,  9,  1,  10, 1,  11,
437:                                    1,  8,  1,  2,  -4, 1,  -4, 0,  -4, 3,  -4, 11, -2, 10, -2, 9,  -2, 8,  -2, 7,  -2, 6,  -2, 5,  -2, 4,  -2, 1,  -1, 0,  -1, 3,  -1, 2,  -1, 4,  0,  5,  0,  6,  0,  7,  0,  11, -1, 10, -1, 9,  -1, 8,  -1, 0,  -2,
438:                                    3,  -2, 2,  -2, 1,  -2, 8,  3,  9,  3,  10, 3,  11, 3,  4,  1,  5,  1,  6,  1,  7,  1,  3,  -3, 2,  -3, 1,  -3, 0,  -3, 7,  -3, 6,  -3, 5,  -3, 4,  -3, 8,  0,  9,  0,  10, 0,  11, 0,  0,  0,  1,  0,  2,  0,  3,
439:                                    0,  4,  0,  5,  0,  6,  0,  7,  0,  8,  0,  9,  0,  10, 0,  11, 0,  1,  3,  2,  3,  3,  3,  0,  3,  11, -2, 10, -2, 9,  -2, 8,  -2, 4,  1,  5,  1,  6,  1,  7,  1,  2,  2,  3,  2,  0,  2,  1,  2,  7,  -3, 6,  -3,
440:                                    5,  -3, 4,  -3, 11, -1, 10, -1, 9,  -1, 8,  -1, 3,  1,  0,  1,  1,  1,  2,  1,  8,  3,  9,  3,  10, 3,  11, 3,  7,  -2, 6,  -2, 5,  -2, 4,  -2, 5,  2,  4,  2,  7,  2,  6,  2,  0,  -3, 1,  -3, 2,  -3, 3,  -3, 9,
441:                                    1,  10, 1,  11, 1,  8,  1,  1,  -1, 0,  -1, 3,  -1, 2,  -1, 5,  -1, 4,  -1, 7,  -1, 6,  -1, 10, 2,  11, 2,  8,  2,  9,  2,  4,  -3, 5,  -3, 6,  -3, 7,  -3, 1,  2,  0,  2,  3,  2,  2,  2,  11, 3,  8,  3,  9,  3,
442:                                    10, 3,  8,  0,  11, 0,  10, 0,  9,  0,  7,  3,  4,  3,  5,  3,  6,  3,  3,  -3, 0,  -3, 1,  -3, 2,  -3, 3,  -3, 2,  -3, 1,  -3, 0,  -3, 6,  2,  7,  2,  4,  2,  5,  2,  9,  -3, 8,  -3, 11, -3, 10, -3, 9,  -3, 10,
443:                                    -3, 11, -3, 8,  -3, 5,  1,  6,  1,  7,  1,  4,  1,  0,  0,  3,  0,  2,  0,  1,  0,  0,  -2, 3,  -2, 2,  -2, 1,  -2, 9,  -4, 8,  -4, 11, -4, 10, -4, 5,  -4, 4,  -4, 7,  -4, 6,  -4, 2,  -4, 1,  -4, 0,  -4, 3,  -4,
444:                                    10, 1,  11, 1,  8,  1,  9,  1,  6,  3,  7,  3,  4,  3,  5,  3,  7,  0,  6,  0,  5,  0,  4,  0,  3,  0,  2,  0,  1,  0,  0,  0,  8,  -2, 11, -2, 10, -2, 9,  -2, 6,  -1, 7,  -1, 4,  -1, 5,  -1, 2,  -1, 3,  -1, 0,
445:                                    -1, 1,  -1, 10, -4, 9,  -4, 8,  -4, 11, -4, 11, -1, 8,  -1, 9,  -1, 10, -1, 4,  -4, 7,  -4, 6,  -4, 5,  -4, 1,  -1, 2,  -1, 3,  -1, 0,  -1, 10, 2,  9,  2,  8,  2,  11, 2,  6,  -2, 5,  -2, 4,  -2, 7,  -2, 2,  2,
446:                                    1,  2,  0,  2,  3,  2,  8,  -2, 9,  -2, 10, -2, 11, -2, 0,  3,  3,  3,  2,  3,  1,  3,  4,  -3, 7,  -3, 6,  -3, 5,  -3, 4,  1,  7,  1,  6,  1,  5,  1,  8,  -3, 11, -3, 10, -3, 9,  -3, 0,  -2, 1,  -2, 2,  -2, 3,
447:                                    -2, 9,  1,  8,  1,  11, 1,  10, 1,  3,  -4, 0,  -4, 1,  -4, 2,  -4, 6,  -1, 5,  -1, 4,  -1, 7,  -1, 5,  -4, 6,  -4, 7,  -4, 4,  -4, 10, -1, 9,  -1, 8,  -1, 11, -1, 1,  3,  0,  3,  3,  3,  2,  3,  7,  -2, 4,  -2,
448:                                    5,  -2, 6,  -2, 11, 2,  8,  2,  9,  2,  10, 2,  2,  -4, 3,  -4, 0,  -4, 1,  -4, 10, -4, 11, -4, 8,  -4, 9,  -4, 1,  -2, 2,  -2, 3,  -2, 0,  -2, 5,  2,  6,  2,  7,  2,  4,  2,  11, 3,  10, 3,  9,  3,  8,  3,  2,
449:                                    1,  1,  1,  0,  1,  3,  1,  7,  0,  4,  0,  5,  0,  6,  0,  6,  3,  5,  3,  4,  3,  7,  3,  9,  0,  10, 0,  11, 0,  8,  0,  3,  1,  2,  1,  1,  1,  0,  1};
450:   static PetscInt hex_hex[]     = {3, -24, 0, -24, 4, -24, 5, -24, 2, -24, 6, -24, 7, -24, 1, -24, 3, -23, 5, -23, 6, -23, 2, -23, 0, -23, 1, -23, 7, -23, 4, -23, 4, -22, 0, -22, 1, -22, 7, -22, 5, -22, 6, -22, 2, -22, 3, -22, 6, -21, 7, -21,
451:                                    1, -21, 2, -21, 5, -21, 3, -21, 0, -21, 4, -21, 1, -20, 2, -20, 6, -20, 7, -20, 0, -20, 4, -20, 5, -20, 3, -20, 6, -19, 2, -19, 3, -19, 5, -19, 7, -19, 4, -19, 0, -19, 1, -19, 4, -18, 5, -18, 3, -18, 0, -18,
452:                                    7, -18, 1, -18, 2, -18, 6, -18, 1, -17, 7, -17, 4, -17, 0, -17, 2, -17, 3, -17, 5, -17, 6, -17, 2, -16, 3, -16, 5, -16, 6, -16, 1, -16, 7, -16, 4, -16, 0, -16, 7, -15, 4, -15, 0, -15, 1, -15, 6, -15, 2, -15,
453:                                    3, -15, 5, -15, 7, -14, 1, -14, 2, -14, 6, -14, 4, -14, 5, -14, 3, -14, 0, -14, 0, -13, 4, -13, 5, -13, 3, -13, 1, -13, 2, -13, 6, -13, 7, -13, 5, -12, 4, -12, 7, -12, 6, -12, 3, -12, 2, -12, 1, -12, 0, -12,
454:                                    7, -11, 6, -11, 5, -11, 4, -11, 1, -11, 0, -11, 3, -11, 2, -11, 0, -10, 1, -10, 7, -10, 4, -10, 3, -10, 5, -10, 6, -10, 2, -10, 4, -9,  7, -9,  6, -9,  5, -9,  0, -9,  3, -9,  2, -9,  1, -9,  5, -8,  6, -8,
455:                                    2, -8,  3, -8,  4, -8,  0, -8,  1, -8,  7, -8,  2, -7,  6, -7,  7, -7,  1, -7,  3, -7,  0, -7,  4, -7,  5, -7,  6, -6,  5, -6,  4, -6,  7, -6,  2, -6,  1, -6,  0, -6,  3, -6,  5, -5,  3, -5,  0, -5,  4, -5,
456:                                    6, -5,  7, -5,  1, -5,  2, -5,  2, -4,  1, -4,  0, -4,  3, -4,  6, -4,  5, -4,  4, -4,  7, -4,  1, -3,  0, -3,  3, -3,  2, -3,  7, -3,  6, -3,  5, -3,  4, -3,  0, -2,  3, -2,  2, -2,  1, -2,  4, -2,  7, -2,
457:                                    6, -2,  5, -2,  3, -1,  2, -1,  1, -1,  0, -1,  5, -1,  4, -1,  7, -1,  6, -1,  0, 0,   1, 0,   2, 0,   3, 0,   4, 0,   5, 0,   6, 0,   7, 0,   1, 1,   2, 1,   3, 1,   0, 1,   7, 1,   4, 1,   5, 1,   6, 1,
458:                                    2, 2,   3, 2,   0, 2,   1, 2,   6, 2,   7, 2,   4, 2,   5, 2,   3, 3,   0, 3,   1, 3,   2, 3,   5, 3,   6, 3,   7, 3,   4, 3,   4, 4,   0, 4,   3, 4,   5, 4,   7, 4,   6, 4,   2, 4,   1, 4,   7, 5,   4, 5,
459:                                    5, 5,   6, 5,   1, 5,   2, 5,   3, 5,   0, 5,   1, 6,   7, 6,   6, 6,   2, 6,   0, 6,   3, 6,   5, 6,   4, 6,   3, 7,   2, 7,   6, 7,   5, 7,   0, 7,   4, 7,   7, 7,   1, 7,   5, 8,   6, 8,   7, 8,   4, 8,
460:                                    3, 8,   0, 8,   1, 8,   2, 8,   4, 9,   7, 9,   1, 9,   0, 9,   5, 9,   3, 9,   2, 9,   6, 9,   4, 10,  5, 10,  6, 10,  7, 10,  0, 10,  1, 10,  2, 10,  3, 10,  6, 11,  7, 11,  4, 11,  5, 11,  2, 11,  3, 11,
461:                                    0, 11,  1, 11,  3, 12,  5, 12,  4, 12,  0, 12,  2, 12,  1, 12,  7, 12,  6, 12,  6, 13,  2, 13,  1, 13,  7, 13,  5, 13,  4, 13,  0, 13,  3, 13,  1, 14,  0, 14,  4, 14,  7, 14,  2, 14,  6, 14,  5, 14,  3, 14,
462:                                    6, 15,  5, 15,  3, 15,  2, 15,  7, 15,  1, 15,  0, 15,  4, 15,  0, 16,  4, 16,  7, 16,  1, 16,  3, 16,  2, 16,  6, 16,  5, 16,  0, 17,  3, 17,  5, 17,  4, 17,  1, 17,  7, 17,  6, 17,  2, 17,  5, 18,  3, 18,
463:                                    2, 18,  6, 18,  4, 18,  7, 18,  1, 18,  0, 18,  7, 19,  6, 19,  2, 19,  1, 19,  4, 19,  0, 19,  3, 19,  5, 19,  2, 20,  1, 20,  7, 20,  6, 20,  3, 20,  5, 20,  4, 20,  0, 20,  7, 21,  1, 21,  0, 21,  4, 21,
464:                                    6, 21,  5, 21,  3, 21,  2, 21,  2, 22,  6, 22,  5, 22,  3, 22,  1, 22,  0, 22,  4, 22,  7, 22,  5, 23,  4, 23,  0, 23,  3, 23,  6, 23,  2, 23,  1, 23,  7, 23};
465:   static PetscInt trip_seg[]    = {1, 0, 2, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0, 0, -1, 2, -1, 1, -1, 1, -1, 0, -1, 2, -1, 2, -1, 1, -1, 0, -1,
466:                                    0, 0, 1, 0, 2, 0, 2, 0, 0, 0, 1, 0, 1, 0, 2, 0, 0, 0, 2, -1, 1, -1, 0, -1, 1, -1, 0, -1, 2, -1, 0, -1, 2, -1, 1, -1};
467:   static PetscInt trip_tri[]    = {1, 1, 2, 1, 0, 1, 3, 1, 2, 2, 0, 2, 1, 2, 3, 2, 0, 0, 1, 0, 2, 0, 3, 0, 2, -1, 1, -1, 0, -1, 3, -3, 0, -2, 2, -2, 1, -2, 3, -1, 1, -3, 0, -3, 2, -3, 3, -2,
468:                                    0, 0, 1, 0, 2, 0, 3, 0, 2, 2, 0, 2, 1, 2, 3, 2, 1, 1, 2, 1, 0, 1, 3, 1, 1, -3, 0, -3, 2, -3, 3, -2, 0, -2, 2, -2, 1, -2, 3, -1, 2, -1, 1, -1, 0, -1, 3, -3};
469:   static PetscInt trip_quad[]   = {4, -1, 5, -1, 3, -1, 1, -1, 2, -1, 0, -1, 5, -1, 3, -1, 4, -1, 2, -1, 0, -1, 1, -1, 3, -1, 4, -1, 5, -1, 0, -1, 1, -1, 2, -1, 0, -3, 2, -3, 1, -3, 3, -3, 5, -3, 4, -3,
470:                                    1, -3, 0, -3, 2, -3, 4, -3, 3, -3, 5, -3, 2, -3, 1, -3, 0, -3, 5, -3, 4, -3, 3, -3, 0, 0,  1, 0,  2, 0,  3, 0,  4, 0,  5, 0,  2, 0,  0, 0,  1, 0,  5, 0,  3, 0,  4, 0,
471:                                    1, 0,  2, 0,  0, 0,  4, 0,  5, 0,  3, 0,  5, 2,  4, 2,  3, 2,  2, 2,  1, 2,  0, 2,  4, 2,  3, 2,  5, 2,  1, 2,  0, 2,  2, 2,  3, 2,  5, 2,  4, 2,  0, 2,  2, 2,  1, 2};
472:   static PetscInt trip_trip[]   = {5, -6, 6, -6, 4, -6, 7, -6, 1, -6, 2, -6, 0, -6, 3, -6, 6, -5, 4, -5, 5, -5, 7, -5, 2, -5, 0, -5, 1, -5, 3, -5, 4, -4, 5, -4, 6, -4, 7, -4, 0, -4, 1, -4, 2, -4, 3, -4,
473:                                    2, -3, 1, -3, 0, -3, 3, -1, 6, -3, 5, -3, 4, -3, 7, -1, 0, -2, 2, -2, 1, -2, 3, -3, 4, -2, 6, -2, 5, -2, 7, -3, 1, -1, 0, -1, 2, -1, 3, -2, 5, -1, 4, -1, 6, -1, 7, -2,
474:                                    0, 0,  1, 0,  2, 0,  3, 0,  4, 0,  5, 0,  6, 0,  7, 0,  2, 1,  0, 1,  1, 1,  3, 1,  6, 1,  4, 1,  5, 1,  7, 1,  1, 2,  2, 2,  0, 2,  3, 2,  5, 2,  6, 2,  4, 2,  7, 2,
475:                                    5, 3,  4, 3,  6, 3,  7, 4,  1, 3,  0, 3,  2, 3,  3, 4,  4, 4,  6, 4,  5, 4,  7, 5,  0, 4,  2, 4,  1, 4,  3, 5,  6, 5,  5, 5,  4, 5,  7, 3,  2, 5,  1, 5,  0, 5,  3, 3};
476:   static PetscInt ttri_tseg[]   = {2, -2, 1, -2, 0, -2, 1, -2, 0, -2, 2, -2, 0, -2, 2, -2, 1, -2, 2, -1, 1, -1, 0, -1, 1, -1, 0, -1, 2, -1, 0, -1, 2, -1, 1, -1,
477:                                    0, 0,  1, 0,  2, 0,  1, 0,  2, 0,  0, 0,  2, 0,  0, 0,  1, 0,  0, 1,  1, 1,  2, 1,  1, 1,  2, 1,  0, 1,  2, 1,  0, 1,  1, 1};
478:   static PetscInt ttri_ttri[]   = {1, -6, 0, -6, 2, -6, 3, -5, 0, -5, 2, -5, 1, -5, 3, -4, 2, -4, 1, -4, 0, -4, 3, -6, 1, -3, 0, -3, 2, -3, 3, -2, 0, -2, 2, -2, 1, -2, 3, -1, 2, -1, 1, -1, 0, -1, 3, -3,
479:                                    0, 0,  1, 0,  2, 0,  3, 0,  1, 1,  2, 1,  0, 1,  3, 1,  2, 2,  0, 2,  1, 2,  3, 2,  0, 3,  1, 3,  2, 3,  3, 3,  1, 4,  2, 4,  0, 4,  3, 4,  2, 5,  0, 5,  1, 5,  3, 5};
480:   static PetscInt tquad_tvert[] = {0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1};
481:   static PetscInt tquad_tseg[]  = {1, 1, 0, 1, 3, 1, 2, 1, 0, 1, 3, 1, 2, 1, 1, 1, 3, 1, 2, 1, 1, 1, 0, 1, 2, 1, 1, 1, 0, 1, 3, 1, 1, 0, 0, 0, 3, 0, 2, 0, 0, 0, 3, 0, 2, 0, 1, 0, 3, 0, 2, 0, 1, 0, 0, 0, 2, 0, 1, 0, 0, 0, 3, 0,
482:                                    0, 0, 1, 0, 2, 0, 3, 0, 1, 0, 2, 0, 3, 0, 0, 0, 2, 0, 3, 0, 0, 0, 1, 0, 3, 0, 0, 0, 1, 0, 2, 0, 0, 1, 1, 1, 2, 1, 3, 1, 1, 1, 2, 1, 3, 1, 0, 1, 2, 1, 3, 1, 0, 1, 1, 1, 3, 1, 0, 1, 1, 1, 2, 1};
483:   static PetscInt tquad_tquad[] = {2,  -8, 1,  -8, 0,  -8, 3,  -8, 1,  -7, 0,  -7, 3,  -7, 2,  -7, 0,  -6, 3,  -6, 2,  -6, 1, -6, 3, -5, 2, -5, 1, -5, 0, -5, 2, -4, 1, -4, 0, -4, 3, -4, 1, -3, 0,
484:                                    -3, 3,  -3, 2,  -3, 0,  -2, 3,  -2, 2,  -2, 1,  -2, 3,  -1, 2,  -1, 1,  -1, 0,  -1, 0,  0, 1,  0, 2,  0, 3,  0, 1,  1, 2,  1, 3,  1, 0,  1, 2,  2, 3,  2, 0,  2,
485:                                    1,  2,  3,  3,  0,  3,  1,  3,  2,  3,  0,  4,  1,  4,  2,  4,  3,  4,  1,  5,  2,  5,  3, 5,  0, 5,  2, 6,  3, 6,  0, 6,  1, 6,  3, 7,  0, 7,  1, 7,  2, 7};

487:   PetscFunctionBeginHot;
488:   *rnew = r;
489:   *onew = o;
490:   if (!so) PetscFunctionReturn(PETSC_SUCCESS);
491:   switch (sct) {
492:   case DM_POLYTOPE_POINT:
493:     break;
494:   case DM_POLYTOPE_POINT_PRISM_TENSOR:
495:     *onew = so < 0 ? -(o + 1) : o;
496:     break;
497:   case DM_POLYTOPE_SEGMENT:
498:     switch (tct) {
499:     case DM_POLYTOPE_POINT:
500:       break;
501:     case DM_POLYTOPE_SEGMENT:
502:       *rnew = seg_seg[(so + 1) * 4 + r * 2];
503:       *onew = DMPolytopeTypeComposeOrientation(tct, o, seg_seg[(so + 1) * 4 + r * 2 + 1]);
504:       break;
505:     default:
506:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
507:     }
508:     break;
509:   case DM_POLYTOPE_TRIANGLE:
510:     switch (tct) {
511:     case DM_POLYTOPE_SEGMENT:
512:       *rnew = tri_seg[(so + 3) * 6 + r * 2];
513:       *onew = DMPolytopeTypeComposeOrientation(tct, o, tri_seg[(so + 3) * 6 + r * 2 + 1]);
514:       break;
515:     case DM_POLYTOPE_TRIANGLE:
516:       *rnew = tri_tri[(so + 3) * 8 + r * 2];
517:       *onew = DMPolytopeTypeComposeOrientation(tct, o, tri_tri[(so + 3) * 8 + r * 2 + 1]);
518:       break;
519:     default:
520:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
521:     }
522:     break;
523:   case DM_POLYTOPE_QUADRILATERAL:
524:     switch (tct) {
525:     case DM_POLYTOPE_POINT:
526:       break;
527:     case DM_POLYTOPE_SEGMENT:
528:       *rnew = quad_seg[(so + 4) * 8 + r * 2];
529:       *onew = DMPolytopeTypeComposeOrientation(tct, o, quad_seg[(so + 4) * 8 + r * 2 + 1]);
530:       break;
531:     case DM_POLYTOPE_QUADRILATERAL:
532:       *rnew = quad_quad[(so + 4) * 8 + r * 2];
533:       *onew = DMPolytopeTypeComposeOrientation(tct, o, quad_quad[(so + 4) * 8 + r * 2 + 1]);
534:       break;
535:     default:
536:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
537:     }
538:     break;
539:   case DM_POLYTOPE_SEG_PRISM_TENSOR:
540:     switch (tct) {
541:     case DM_POLYTOPE_POINT_PRISM_TENSOR:
542:       *rnew = tseg_seg[(so + 2) * 2 + r * 2];
543:       *onew = DMPolytopeTypeComposeOrientation(tct, o, tseg_seg[(so + 2) * 2 + r * 2 + 1]);
544:       break;
545:     case DM_POLYTOPE_SEG_PRISM_TENSOR:
546:       *rnew = tseg_tseg[(so + 2) * 4 + r * 2];
547:       *onew = DMPolytopeTypeComposeOrientation(tct, o, tseg_tseg[(so + 2) * 4 + r * 2 + 1]);
548:       break;
549:     default:
550:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
551:     }
552:     break;
553:   case DM_POLYTOPE_TETRAHEDRON:
554:     switch (tct) {
555:     case DM_POLYTOPE_SEGMENT:
556:       *rnew = tet_seg[(so + 12) * 2 + r * 2];
557:       *onew = DMPolytopeTypeComposeOrientation(tct, o, tet_seg[(so + 12) * 2 + r * 2 + 1]);
558:       break;
559:     case DM_POLYTOPE_TRIANGLE:
560:       *rnew = tet_tri[(so + 12) * 16 + r * 2];
561:       *onew = DMPolytopeTypeComposeOrientation(tct, o, tet_tri[(so + 12) * 16 + r * 2 + 1]);
562:       break;
563:     case DM_POLYTOPE_TETRAHEDRON:
564:       *rnew = tet_tet[(so + 12) * 16 + r * 2];
565:       *onew = DMPolytopeTypeComposeOrientation(tct, o, tet_tet[(so + 12) * 16 + r * 2 + 1]);
566:       break;
567:     default:
568:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
569:     }
570:     break;
571:   case DM_POLYTOPE_HEXAHEDRON:
572:     switch (tct) {
573:     case DM_POLYTOPE_POINT:
574:       break;
575:     case DM_POLYTOPE_SEGMENT:
576:       *rnew = hex_seg[(so + 24) * 12 + r * 2];
577:       *onew = DMPolytopeTypeComposeOrientation(tct, o, hex_seg[(so + 24) * 12 + r * 2 + 1]);
578:       break;
579:     case DM_POLYTOPE_QUADRILATERAL:
580:       *rnew = hex_quad[(so + 24) * 24 + r * 2];
581:       *onew = DMPolytopeTypeComposeOrientation(tct, o, hex_quad[(so + 24) * 24 + r * 2 + 1]);
582:       break;
583:     case DM_POLYTOPE_HEXAHEDRON:
584:       *rnew = hex_hex[(so + 24) * 16 + r * 2];
585:       *onew = DMPolytopeTypeComposeOrientation(tct, o, hex_hex[(so + 24) * 16 + r * 2 + 1]);
586:       break;
587:     default:
588:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
589:     }
590:     break;
591:   case DM_POLYTOPE_TRI_PRISM:
592:     switch (tct) {
593:     case DM_POLYTOPE_SEGMENT:
594:       *rnew = trip_seg[(so + 6) * 6 + r * 2];
595:       *onew = DMPolytopeTypeComposeOrientation(tct, o, trip_seg[(so + 6) * 6 + r * 2 + 1]);
596:       break;
597:     case DM_POLYTOPE_TRIANGLE:
598:       *rnew = trip_tri[(so + 6) * 8 + r * 2];
599:       *onew = DMPolytopeTypeComposeOrientation(tct, o, trip_tri[(so + 6) * 8 + r * 2 + 1]);
600:       break;
601:     case DM_POLYTOPE_QUADRILATERAL:
602:       *rnew = trip_quad[(so + 6) * 12 + r * 2];
603:       *onew = DMPolytopeTypeComposeOrientation(tct, o, trip_quad[(so + 6) * 12 + r * 2 + 1]);
604:       break;
605:     case DM_POLYTOPE_TRI_PRISM:
606:       *rnew = trip_trip[(so + 6) * 16 + r * 2];
607:       *onew = DMPolytopeTypeComposeOrientation(tct, o, trip_trip[(so + 6) * 16 + r * 2 + 1]);
608:       break;
609:     default:
610:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
611:     }
612:     break;
613:   case DM_POLYTOPE_TRI_PRISM_TENSOR:
614:     switch (tct) {
615:     case DM_POLYTOPE_SEG_PRISM_TENSOR:
616:       *rnew = ttri_tseg[(so + 6) * 6 + r * 2];
617:       *onew = DMPolytopeTypeComposeOrientation(tct, o, ttri_tseg[(so + 6) * 6 + r * 2 + 1]);
618:       break;
619:     case DM_POLYTOPE_TRI_PRISM_TENSOR:
620:       *rnew = ttri_ttri[(so + 6) * 8 + r * 2];
621:       *onew = DMPolytopeTypeComposeOrientation(tct, o, ttri_ttri[(so + 6) * 8 + r * 2 + 1]);
622:       break;
623:     default:
624:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
625:     }
626:     break;
627:   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
628:     switch (tct) {
629:     case DM_POLYTOPE_POINT_PRISM_TENSOR:
630:       *rnew = tquad_tvert[(so + 8) * 2 + r * 2];
631:       *onew = DMPolytopeTypeComposeOrientation(tct, o, tquad_tvert[(so + 8) * 2 + r * 2 + 1]);
632:       break;
633:     case DM_POLYTOPE_SEG_PRISM_TENSOR:
634:       *rnew = tquad_tseg[(so + 8) * 8 + r * 2];
635:       *onew = DMPolytopeTypeComposeOrientation(tct, o, tquad_tseg[(so + 8) * 8 + r * 2 + 1]);
636:       break;
637:     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
638:       *rnew = tquad_tquad[(so + 8) * 8 + r * 2];
639:       *onew = DMPolytopeTypeComposeOrientation(tct, o, tquad_tquad[(so + 8) * 8 + r * 2 + 1]);
640:       break;
641:     default:
642:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
643:     }
644:     break;
645:   default:
646:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported cell type %s", DMPolytopeTypes[sct]);
647:   }
648:   PetscFunctionReturn(PETSC_SUCCESS);
649: }

651: PetscErrorCode DMPlexTransformCellRefine_Regular(DMPlexTransform tr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
652: {
653:   /* All vertices remain in the refined mesh */
654:   static DMPolytopeType vertexT[] = {DM_POLYTOPE_POINT};
655:   static PetscInt       vertexS[] = {1};
656:   static PetscInt       vertexC[] = {0};
657:   static PetscInt       vertexO[] = {0};
658:   /* Split all edges with a new vertex, making two new 2 edges
659:      0--0--0--1--1
660:   */
661:   static DMPolytopeType segT[] = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT};
662:   static PetscInt       segS[] = {1, 2};
663:   static PetscInt       segC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
664:   static PetscInt       segO[] = {0, 0, 0, 0};
665:   /* Do not split tensor edges */
666:   static DMPolytopeType tvertT[] = {DM_POLYTOPE_POINT_PRISM_TENSOR};
667:   static PetscInt       tvertS[] = {1};
668:   static PetscInt       tvertC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
669:   static PetscInt       tvertO[] = {0, 0};
670:   /* Add 3 edges inside every triangle, making 4 new triangles.
671:    2
672:    |\
673:    | \
674:    |  \
675:    0   1
676:    | C  \
677:    |     \
678:    |      \
679:    2---1---1
680:    |\  D  / \
681:    1 2   0   0
682:    |A \ /  B  \
683:    0-0-0---1---1
684:   */
685:   static DMPolytopeType triT[] = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE};
686:   static PetscInt       triS[] = {3, 4};
687:   static PetscInt triC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 2};
688:   static PetscInt triO[] = {0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0};
689:   /* Add a vertex in the center of each quadrilateral, and 4 edges inside, making 4 new quads.
690:      3----1----2----0----2
691:      |         |         |
692:      0    D    2    C    1
693:      |         |         |
694:      3----3----0----1----1
695:      |         |         |
696:      1    A    0    B    0
697:      |         |         |
698:      0----0----0----1----1
699:   */
700:   static DMPolytopeType quadT[] = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
701:   static PetscInt       quadS[] = {1, 4, 4};
702:   static PetscInt quadC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0};
703:   static PetscInt quadO[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, -1, 0, 0};
704:   /* Add 1 edge inside every tensor quad, making 2 new tensor quads
705:      2----2----1----3----3
706:      |         |         |
707:      |         |         |
708:      |         |         |
709:      4    A    6    B    5
710:      |         |         |
711:      |         |         |
712:      |         |         |
713:      0----0----0----1----1
714:   */
715:   static DMPolytopeType tsegT[] = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR};
716:   static PetscInt       tsegS[] = {1, 2};
717:   static PetscInt tsegC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 3, 0};
718:   static PetscInt tsegO[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
719:   /* Add 1 edge and 8 triangles inside every cell, making 8 new tets
720:      The vertices of our reference tet are [(-1, -1, -1), (-1, 1, -1), (1, -1, -1), (-1, -1, 1)], which we call [v0, v1, v2, v3]. The first
721:      three edges are [v0, v1], [v1, v2], [v2, v0] called e0, e1, and e2, and then three edges to the top point [v0, v3], [v1, v3], [v2, v3]
722:      called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are
723:        [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3]
724:      The first four tets just cut off the corners, using the replica notation for new vertices,
725:        [v0,      (e0, 0), (e2, 0), (e3, 0)]
726:        [(e0, 0), v1,      (e1, 0), (e4, 0)]
727:        [(e2, 0), (e1, 0), v2,      (e5, 0)]
728:        [(e3, 0), (e4, 0), (e5, 0), v3     ]
729:      The next four tets match a vertex to the newly created faces from cutting off those first tets.
730:        [(e2, 0), (e3, 0), (e0, 0), (e5, 0)]
731:        [(e4, 0), (e1, 0), (e0, 0), (e5, 0)]
732:        [(e5, 0), (e0, 0), (e2, 0), (e1, 0)]
733:        [(e5, 0), (e0, 0), (e4, 0), (e3, 0)]
734:      We can see that a new edge is introduced in the cell [(e0, 0), (e5, 0)] which we call (-1, 0). The first four faces created are
735:        [(e2, 0), (e0, 0), (e3, 0)]
736:        [(e0, 0), (e1, 0), (e4, 0)]
737:        [(e2, 0), (e5, 0), (e1, 0)]
738:        [(e3, 0), (e4, 0), (e5, 0)]
739:      The next four, from the second group of tets, are
740:        [(e2, 0), (e0, 0), (e5, 0)]
741:        [(e4, 0), (e0, 0), (e5, 0)]
742:        [(e0, 0), (e1, 0), (e5, 0)]
743:        [(e5, 0), (e3, 0), (e0, 0)]
744:      I could write a program to generate these orientations by comparing the faces from GetRawFaces() with my existing table.
745:    */
746:   static DMPolytopeType tetT[] = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_TETRAHEDRON};
747:   static PetscInt       tetS[] = {1, 8, 8};
748:   static PetscInt tetC[] = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 2, 2, 1, 0, DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 0, 1, DM_POLYTOPE_TRIANGLE, 1, 1, 2, DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_TRIANGLE, 1, 3, 1, DM_POLYTOPE_TRIANGLE, 1, 0, 2, DM_POLYTOPE_TRIANGLE, 0, 2, DM_POLYTOPE_TRIANGLE, 1, 2, 1, DM_POLYTOPE_TRIANGLE, 1, 3, 0, DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_TRIANGLE, 1, 1, 1, DM_POLYTOPE_TRIANGLE, 1, 2, 2, DM_POLYTOPE_TRIANGLE, 1, 3, 2, DM_POLYTOPE_TRIANGLE, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 2, 3, DM_POLYTOPE_TRIANGLE, 0, 4, DM_POLYTOPE_TRIANGLE, 0, 7, DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_TRIANGLE, 1, 3, 3, DM_POLYTOPE_TRIANGLE, 0, 5, DM_POLYTOPE_TRIANGLE, 0, 6, DM_POLYTOPE_TRIANGLE, 0, 4, DM_POLYTOPE_TRIANGLE, 0, 6, DM_POLYTOPE_TRIANGLE, 0, 2, DM_POLYTOPE_TRIANGLE, 1, 0, 3, DM_POLYTOPE_TRIANGLE, 0, 5, DM_POLYTOPE_TRIANGLE, 0, 7, DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_TRIANGLE, 1, 1, 3};
749:   static PetscInt tetO[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, -1, -1, 1, 0, 0, -1, -1, -3, 2, -1, 0, -1, 1};
750:   /* Add a vertex in the center of each cell, add 6 edges and 12 quads inside every cell, making 8 new hexes
751:      The vertices of our reference hex are (-1, -1, -1), (-1, 1, -1), (1, 1, -1), (1, -1, -1), (-1, -1, 1), (1, -1, 1), (1, 1, 1), (-1, 1, 1) which we call [v0, v1, v2, v3, v4, v5, v6, v7]. The fours edges around the bottom [v0, v1], [v1, v2], [v2, v3], [v3, v0] are [e0, e1, e2, e3], and likewise around the top [v4, v5], [v5, v6], [v6, v7], [v7, v4] are [e4, e5, e6, e7]. Finally [v0, v4], [v1, v7], [v2, v6], [v3, v5] are [e9, e10, e11, e8]. The faces of a hex, given in DMPlexGetRawFaces_Internal(), oriented with outward normals, are
752:        [v0, v1, v2, v3] f0 bottom
753:        [v4, v5, v6, v7] f1 top
754:        [v0, v3, v5, v4] f2 front
755:        [v2, v1, v7, v6] f3 back
756:        [v3, v2, v6, v5] f4 right
757:        [v0, v4, v7, v1] f5 left
758:      The eight hexes are divided into four on the bottom, and four on the top,
759:        [v0,      (e0, 0),  (f0, 0),  (e3, 0),  (e9, 0), (f2, 0),  (c0, 0),  (f5, 0)]
760:        [(e0, 0), v1,       (e1, 0),  (f0, 0),  (f5, 0), (c0, 0),  (f3, 0),  (e10, 0)]
761:        [(f0, 0), (e1, 0),  v2,       (e2, 0),  (c0, 0), (f4, 0),  (e11, 0), (f3, 0)]
762:        [(e3, 0), (f0, 0),  (e2, 0),  v3,       (f2, 0), (e8, 0),  (f4, 0),  (c0, 0)]
763:        [(e9, 0), (f5, 0),  (c0, 0),  (f2, 0),  v4,      (e4, 0),  (f1, 0),  (e7, 0)]
764:        [(f2, 0), (c0, 0),  (f4, 0),  (e8, 0),  (e4, 0), v5,       (e5, 0),  (f1, 0)]
765:        [(c0, 0), (f3, 0),  (e11, 0), (f4, 0),  (f1, 0), (e5, 0),  v6,       (e6, 0)]
766:        [(f5, 0), (e10, 0), (f3, 0),  (c0, 0),  (e7, 0), (f1, 0),  (e6, 0),  v7]
767:      The 6 internal edges will go from the faces to the central vertex. The 12 internal faces can be divided into groups of 4 by the plane on which they sit. First the faces on the x-y plane are,
768:        [(e9, 0), (f2, 0),  (c0, 0),  (f5, 0)]
769:        [(f5, 0), (c0, 0),  (f3, 0),  (e10, 0)]
770:        [(c0, 0), (f4, 0),  (e11, 0), (f3, 0)]
771:        [(f2, 0), (e8, 0),  (f4, 0),  (c0, 0)]
772:      and on the x-z plane,
773:        [(f0, 0), (e0, 0), (f5, 0), (c0, 0)]
774:        [(c0, 0), (f5, 0), (e7, 0), (f1, 0)]
775:        [(f4, 0), (c0, 0), (f1, 0), (e5, 0)]
776:        [(e2, 0), (f0, 0), (c0, 0), (f4, 0)]
777:      and on the y-z plane,
778:        [(e3, 0), (f2, 0), (c0, 0), (f0, 0)]
779:        [(f2, 0), (e4, 0), (f1, 0), (c0, 0)]
780:        [(c0, 0), (f1, 0), (e6, 0), (f3, 0)]
781:        [(f0, 0), (c0, 0), (f3, 0), (e1, 0)]
782:   */
783:   static DMPolytopeType hexT[] = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
784:   static PetscInt       hexS[] = {1, 6, 12, 8};
785:   static PetscInt hexC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 5, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 5, DM_POLYTOPE_SEGMENT, 1, 5, 0, DM_POLYTOPE_SEGMENT, 0, 5, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 5, 2, DM_POLYTOPE_SEGMENT, 0, 4, DM_POLYTOPE_SEGMENT, 1, 4, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3, DM_POLYTOPE_SEGMENT, 0, 4, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 5, 3, DM_POLYTOPE_SEGMENT, 0, 5, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 5, DM_POLYTOPE_SEGMENT, 1, 5, 1, DM_POLYTOPE_SEGMENT, 1, 1, 3, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 4, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 4, 2, DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 4, DM_POLYTOPE_SEGMENT, 1, 4, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 0, 3, DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 0, 4, DM_POLYTOPE_QUADRILATERAL, 0, 8, DM_POLYTOPE_QUADRILATERAL, 1, 5, 0, DM_POLYTOPE_QUADRILATERAL, 1, 0, 1, DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 0, 4, DM_POLYTOPE_QUADRILATERAL, 1, 3, 1, DM_POLYTOPE_QUADRILATERAL, 0, 11, DM_POLYTOPE_QUADRILATERAL, 1, 5, 3, DM_POLYTOPE_QUADRILATERAL, 1, 0, 2, DM_POLYTOPE_QUADRILATERAL, 0, 2, DM_POLYTOPE_QUADRILATERAL, 0, 7, DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 1, 4, 1, DM_POLYTOPE_QUADRILATERAL, 0, 11, DM_POLYTOPE_QUADRILATERAL, 1, 0, 3, DM_POLYTOPE_QUADRILATERAL, 0, 3, DM_POLYTOPE_QUADRILATERAL, 1, 2, 1, DM_POLYTOPE_QUADRILATERAL, 0, 7, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0, DM_POLYTOPE_QUADRILATERAL, 0, 8, DM_POLYTOPE_QUADRILATERAL, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 3, DM_POLYTOPE_QUADRILATERAL, 0, 5, DM_POLYTOPE_QUADRILATERAL, 0, 9, DM_POLYTOPE_QUADRILATERAL, 1, 5, 1, DM_POLYTOPE_QUADRILATERAL, 0, 3, DM_POLYTOPE_QUADRILATERAL, 1, 1, 1, DM_POLYTOPE_QUADRILATERAL, 1, 2, 2, DM_POLYTOPE_QUADRILATERAL, 0, 6, DM_POLYTOPE_QUADRILATERAL, 1, 4, 3, DM_POLYTOPE_QUADRILATERAL, 0, 9, DM_POLYTOPE_QUADRILATERAL, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 1, 2, DM_POLYTOPE_QUADRILATERAL, 0, 6, DM_POLYTOPE_QUADRILATERAL, 1, 3, 3, DM_POLYTOPE_QUADRILATERAL, 1, 4, 2, DM_POLYTOPE_QUADRILATERAL, 0, 10, DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 1, 3, DM_POLYTOPE_QUADRILATERAL, 0, 5, DM_POLYTOPE_QUADRILATERAL, 1, 3, 2, DM_POLYTOPE_QUADRILATERAL, 0, 10, DM_POLYTOPE_QUADRILATERAL, 1, 5, 2};
786:   static PetscInt hexO[] = {0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0,  0, 0, 0, -1, -1, 0,  -1, -1, 0, -1, -1, 0, 0, -1, 0, 0, -1, -1, 0, 0,  -1, -1, -1, 0,  0, 0,  -1, -1, 0, 0, 0, -1, -1, 0,  0, -1, -1, -1, 0, 0,  -1, -1, -1,
787:                             0, 0, 0, -1, -1, 0, 0, 0, 0, 0, -2, 0, 0, 0, -3, 0,  -2, 0,  0,  0, -3, 0,  0, 0, 0,  0, 0, 0,  0,  0, -2, 0,  0,  0,  -2, 0, -2, 0,  0,  0, 0, 0, -2, 0,  -3, 0, 0,  0,  -2, 0, -3, 0,  -2, 0};
788:   /* Add 3 quads inside every triangular prism, making 4 new prisms. */
789:   static DMPolytopeType tripT[] = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_TRI_PRISM};
790:   static PetscInt       tripS[] = {3, 4, 6, 8};
791:   static PetscInt tripC[] = {DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 4, 1, DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 4, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 4, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 4, 2, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 4, 2, DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 4, 1, DM_POLYTOPE_TRIANGLE, 1, 0, 2, DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 2, 1, DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 0, 1, DM_POLYTOPE_TRIANGLE, 0, 2, DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 3, 1, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0, DM_POLYTOPE_TRIANGLE, 1, 0, 3, DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_QUADRILATERAL, 0, 0, DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 0, 2, DM_POLYTOPE_TRIANGLE, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 3, DM_POLYTOPE_QUADRILATERAL, 0, 5, DM_POLYTOPE_QUADRILATERAL, 1, 4, 2, DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_TRIANGLE, 1, 1, 1, DM_POLYTOPE_QUADRILATERAL, 1, 2, 2, DM_POLYTOPE_QUADRILATERAL, 1, 3, 3, DM_POLYTOPE_QUADRILATERAL, 0, 3, DM_POLYTOPE_TRIANGLE, 0, 2, DM_POLYTOPE_TRIANGLE, 1, 1, 2, DM_POLYTOPE_QUADRILATERAL, 0, 4, DM_POLYTOPE_QUADRILATERAL, 1, 3, 2, DM_POLYTOPE_QUADRILATERAL, 1, 4, 3, DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_TRIANGLE, 1, 1, 3, DM_POLYTOPE_QUADRILATERAL, 0, 3, DM_POLYTOPE_QUADRILATERAL, 0, 4, DM_POLYTOPE_QUADRILATERAL, 0, 5};
792:   static PetscInt tripO[] = {0, 0, 0, 0, 0,  0, 0, -1, -1, -1, 0,  -1, -1, -1, 0, 0, 0, 0, -1, 0, -1, -1, -1, 0, -1, -1, -1, 0, -1, -1, 0,  -1, -1, 0,  0, -1, -1, 0, 0, -1, -1,
793:                              0, 0, 0, 0, -3, 0, 0, 0,  0,  0,  -3, 0,  0,  -3, 0, 0, 2, 0, 0,  0, 0,  -2, 0,  0, -3, 0,  -2, 0, 0,  0,  -3, -2, 0,  -3, 0, 0,  -2, 0, 0, 0,  0};
794:   /* Add 3 tensor quads inside every tensor triangular prism, making 4 new prisms.
795:       2
796:       |\
797:       | \
798:       |  \
799:       0---1

801:       2

803:       0   1

805:       2
806:       |\
807:       | \
808:       |  \
809:       0---1
810:   */
811:   static DMPolytopeType ttriT[] = {DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_TRI_PRISM_TENSOR};
812:   static PetscInt       ttriS[] = {3, 4};
813:   static PetscInt ttriC[] = {DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 1, DM_POLYTOPE_TRIANGLE, 1, 0, 1, DM_POLYTOPE_TRIANGLE, 1, 1, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 0, 2, DM_POLYTOPE_TRIANGLE, 1, 1, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_TRIANGLE, 1, 0, 3, DM_POLYTOPE_TRIANGLE, 1, 1, 3, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 2};
814:   static PetscInt ttriO[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0};
815:   /* Add 1 edge and 4 tensor quads inside every tensor quad prism, making 4 new prisms. */
816:   static DMPolytopeType tquadT[] = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
817:   static PetscInt       tquadS[] = {1, 4, 4};
818:   static PetscInt tquadC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, DM_POLYTOPE_SEGMENT, 1, 0, 3, DM_POLYTOPE_SEGMENT, 1, 1, 3, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 5, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 3, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 5, 1, DM_POLYTOPE_QUADRILATERAL, 1, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 1, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 1, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 0, 3, DM_POLYTOPE_QUADRILATERAL, 1, 1, 3, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 3, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 5, 0};
819:   static PetscInt tquadO[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0};
820:   /* Add 4 edges, 12 triangles, 1 quad, 4 tetrahedra, and 6 pyramids inside every pyramid. */
821:   static DMPolytopeType tpyrT[] = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_TETRAHEDRON, DM_POLYTOPE_PYRAMID};
822:   static PetscInt       tpyrS[] = {4, 12, 1, 4, 6};
823:   static PetscInt       tpyrC[] = {
824:     DM_POLYTOPE_POINT,
825:     2,
826:     1,
827:     1,
828:     0,
829:     DM_POLYTOPE_POINT,
830:     1,
831:     0,
832:     0,
833:     DM_POLYTOPE_POINT,
834:     2,
835:     2,
836:     1,
837:     0,
838:     DM_POLYTOPE_POINT,
839:     1,
840:     0,
841:     0,
842:     DM_POLYTOPE_POINT,
843:     2,
844:     3,
845:     1,
846:     0,
847:     DM_POLYTOPE_POINT,
848:     1,
849:     0,
850:     0,
851:     DM_POLYTOPE_POINT,
852:     2,
853:     4,
854:     1,
855:     0,
856:     DM_POLYTOPE_POINT,
857:     1,
858:     0,
859:     0,
860:     /* These four triangle face out of the bottom pyramid */
861:     DM_POLYTOPE_SEGMENT,
862:     1,
863:     1,
864:     1,
865:     DM_POLYTOPE_SEGMENT,
866:     0,
867:     3,
868:     DM_POLYTOPE_SEGMENT,
869:     0,
870:     0,
871:     DM_POLYTOPE_SEGMENT,
872:     1,
873:     2,
874:     1,
875:     DM_POLYTOPE_SEGMENT,
876:     0,
877:     0,
878:     DM_POLYTOPE_SEGMENT,
879:     0,
880:     1,
881:     DM_POLYTOPE_SEGMENT,
882:     1,
883:     3,
884:     1,
885:     DM_POLYTOPE_SEGMENT,
886:     0,
887:     1,
888:     DM_POLYTOPE_SEGMENT,
889:     0,
890:     2,
891:     DM_POLYTOPE_SEGMENT,
892:     1,
893:     4,
894:     1,
895:     DM_POLYTOPE_SEGMENT,
896:     0,
897:     2,
898:     DM_POLYTOPE_SEGMENT,
899:     0,
900:     3,
901:     /* These eight triangles face out of the corner pyramids */
902:     DM_POLYTOPE_SEGMENT,
903:     1,
904:     0,
905:     3,
906:     DM_POLYTOPE_SEGMENT,
907:     0,
908:     3,
909:     DM_POLYTOPE_SEGMENT,
910:     1,
911:     1,
912:     2,
913:     DM_POLYTOPE_SEGMENT,
914:     1,
915:     0,
916:     2,
917:     DM_POLYTOPE_SEGMENT,
918:     0,
919:     0,
920:     DM_POLYTOPE_SEGMENT,
921:     1,
922:     2,
923:     2,
924:     DM_POLYTOPE_SEGMENT,
925:     1,
926:     0,
927:     1,
928:     DM_POLYTOPE_SEGMENT,
929:     0,
930:     1,
931:     DM_POLYTOPE_SEGMENT,
932:     1,
933:     3,
934:     2,
935:     DM_POLYTOPE_SEGMENT,
936:     1,
937:     0,
938:     0,
939:     DM_POLYTOPE_SEGMENT,
940:     0,
941:     2,
942:     DM_POLYTOPE_SEGMENT,
943:     1,
944:     4,
945:     2,
946:     DM_POLYTOPE_SEGMENT,
947:     1,
948:     0,
949:     3,
950:     DM_POLYTOPE_SEGMENT,
951:     1,
952:     1,
953:     0,
954:     DM_POLYTOPE_SEGMENT,
955:     0,
956:     0,
957:     DM_POLYTOPE_SEGMENT,
958:     1,
959:     0,
960:     2,
961:     DM_POLYTOPE_SEGMENT,
962:     1,
963:     2,
964:     0,
965:     DM_POLYTOPE_SEGMENT,
966:     0,
967:     1,
968:     DM_POLYTOPE_SEGMENT,
969:     1,
970:     0,
971:     1,
972:     DM_POLYTOPE_SEGMENT,
973:     1,
974:     3,
975:     0,
976:     DM_POLYTOPE_SEGMENT,
977:     0,
978:     2,
979:     DM_POLYTOPE_SEGMENT,
980:     1,
981:     0,
982:     0,
983:     DM_POLYTOPE_SEGMENT,
984:     1,
985:     4,
986:     0,
987:     DM_POLYTOPE_SEGMENT,
988:     0,
989:     3,
990:     /* This quad faces out of the bottom pyramid */
991:     DM_POLYTOPE_SEGMENT,
992:     1,
993:     1,
994:     1,
995:     DM_POLYTOPE_SEGMENT,
996:     1,
997:     2,
998:     1,
999:     DM_POLYTOPE_SEGMENT,
1000:     1,
1001:     3,
1002:     1,
1003:     DM_POLYTOPE_SEGMENT,
1004:     1,
1005:     4,
1006:     1,
1007:     /* The bottom face of each tet is on the triangular face */
1008:     DM_POLYTOPE_TRIANGLE,
1009:     1,
1010:     1,
1011:     3,
1012:     DM_POLYTOPE_TRIANGLE,
1013:     0,
1014:     8,
1015:     DM_POLYTOPE_TRIANGLE,
1016:     0,
1017:     4,
1018:     DM_POLYTOPE_TRIANGLE,
1019:     0,
1020:     0,
1021:     DM_POLYTOPE_TRIANGLE,
1022:     1,
1023:     2,
1024:     3,
1025:     DM_POLYTOPE_TRIANGLE,
1026:     0,
1027:     9,
1028:     DM_POLYTOPE_TRIANGLE,
1029:     0,
1030:     5,
1031:     DM_POLYTOPE_TRIANGLE,
1032:     0,
1033:     1,
1034:     DM_POLYTOPE_TRIANGLE,
1035:     1,
1036:     3,
1037:     3,
1038:     DM_POLYTOPE_TRIANGLE,
1039:     0,
1040:     10,
1041:     DM_POLYTOPE_TRIANGLE,
1042:     0,
1043:     6,
1044:     DM_POLYTOPE_TRIANGLE,
1045:     0,
1046:     2,
1047:     DM_POLYTOPE_TRIANGLE,
1048:     1,
1049:     4,
1050:     3,
1051:     DM_POLYTOPE_TRIANGLE,
1052:     0,
1053:     11,
1054:     DM_POLYTOPE_TRIANGLE,
1055:     0,
1056:     7,
1057:     DM_POLYTOPE_TRIANGLE,
1058:     0,
1059:     3,
1060:     /* The front face of all pyramids is toward the front */
1061:     DM_POLYTOPE_QUADRILATERAL,
1062:     1,
1063:     0,
1064:     0,
1065:     DM_POLYTOPE_TRIANGLE,
1066:     1,
1067:     1,
1068:     0,
1069:     DM_POLYTOPE_TRIANGLE,
1070:     0,
1071:     4,
1072:     DM_POLYTOPE_TRIANGLE,
1073:     0,
1074:     11,
1075:     DM_POLYTOPE_TRIANGLE,
1076:     1,
1077:     4,
1078:     1,
1079:     DM_POLYTOPE_QUADRILATERAL,
1080:     1,
1081:     0,
1082:     3,
1083:     DM_POLYTOPE_TRIANGLE,
1084:     1,
1085:     1,
1086:     1,
1087:     DM_POLYTOPE_TRIANGLE,
1088:     1,
1089:     2,
1090:     0,
1091:     DM_POLYTOPE_TRIANGLE,
1092:     0,
1093:     5,
1094:     DM_POLYTOPE_TRIANGLE,
1095:     0,
1096:     8,
1097:     DM_POLYTOPE_QUADRILATERAL,
1098:     1,
1099:     0,
1100:     2,
1101:     DM_POLYTOPE_TRIANGLE,
1102:     0,
1103:     9,
1104:     DM_POLYTOPE_TRIANGLE,
1105:     1,
1106:     2,
1107:     1,
1108:     DM_POLYTOPE_TRIANGLE,
1109:     1,
1110:     3,
1111:     0,
1112:     DM_POLYTOPE_TRIANGLE,
1113:     0,
1114:     6,
1115:     DM_POLYTOPE_QUADRILATERAL,
1116:     1,
1117:     0,
1118:     1,
1119:     DM_POLYTOPE_TRIANGLE,
1120:     0,
1121:     7,
1122:     DM_POLYTOPE_TRIANGLE,
1123:     0,
1124:     10,
1125:     DM_POLYTOPE_TRIANGLE,
1126:     1,
1127:     3,
1128:     1,
1129:     DM_POLYTOPE_TRIANGLE,
1130:     1,
1131:     4,
1132:     0,
1133:     DM_POLYTOPE_QUADRILATERAL,
1134:     0,
1135:     0,
1136:     DM_POLYTOPE_TRIANGLE,
1137:     1,
1138:     1,
1139:     2,
1140:     DM_POLYTOPE_TRIANGLE,
1141:     1,
1142:     2,
1143:     2,
1144:     DM_POLYTOPE_TRIANGLE,
1145:     1,
1146:     3,
1147:     2,
1148:     DM_POLYTOPE_TRIANGLE,
1149:     1,
1150:     4,
1151:     2,
1152:     DM_POLYTOPE_QUADRILATERAL,
1153:     0,
1154:     0,
1155:     DM_POLYTOPE_TRIANGLE,
1156:     0,
1157:     0,
1158:     DM_POLYTOPE_TRIANGLE,
1159:     0,
1160:     3,
1161:     DM_POLYTOPE_TRIANGLE,
1162:     0,
1163:     2,
1164:     DM_POLYTOPE_TRIANGLE,
1165:     0,
1166:     1,
1167:   };
1168:   static PetscInt tpyrO[] = {0,  0, 0,  0,  0,  0, 0,  0,  0,  0, -1, 0,  0,  -1, 0,  0,  -1, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0,  -1, 0, 0, -1, 0, 0, -1, -1, -1,
1169:                              -1, 0, -3, -2, -3, 0, -3, -2, -3, 0, -3, -2, -3, 0,  -3, -2, -3, 0, 0, 0,  0, 0,  0, 0, 0,  0, 0, 0,  0, 0, 0,  0, 0,  0, 0, 0,  0, -2, 0,  0, 0, 0,  1, 0, 0,  0,  0};

1171:   PetscFunctionBegin;
1172:   if (rt) *rt = 0;
1173:   switch (source) {
1174:   case DM_POLYTOPE_POINT:
1175:     *Nt     = 1;
1176:     *target = vertexT;
1177:     *size   = vertexS;
1178:     *cone   = vertexC;
1179:     *ornt   = vertexO;
1180:     break;
1181:   case DM_POLYTOPE_SEGMENT:
1182:     *Nt     = 2;
1183:     *target = segT;
1184:     *size   = segS;
1185:     *cone   = segC;
1186:     *ornt   = segO;
1187:     break;
1188:   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1189:     *Nt     = 1;
1190:     *target = tvertT;
1191:     *size   = tvertS;
1192:     *cone   = tvertC;
1193:     *ornt   = tvertO;
1194:     break;
1195:   case DM_POLYTOPE_TRIANGLE:
1196:     *Nt     = 2;
1197:     *target = triT;
1198:     *size   = triS;
1199:     *cone   = triC;
1200:     *ornt   = triO;
1201:     break;
1202:   case DM_POLYTOPE_QUADRILATERAL:
1203:     *Nt     = 3;
1204:     *target = quadT;
1205:     *size   = quadS;
1206:     *cone   = quadC;
1207:     *ornt   = quadO;
1208:     break;
1209:   case DM_POLYTOPE_SEG_PRISM_TENSOR:
1210:     *Nt     = 2;
1211:     *target = tsegT;
1212:     *size   = tsegS;
1213:     *cone   = tsegC;
1214:     *ornt   = tsegO;
1215:     break;
1216:   case DM_POLYTOPE_TETRAHEDRON:
1217:     *Nt     = 3;
1218:     *target = tetT;
1219:     *size   = tetS;
1220:     *cone   = tetC;
1221:     *ornt   = tetO;
1222:     break;
1223:   case DM_POLYTOPE_HEXAHEDRON:
1224:     *Nt     = 4;
1225:     *target = hexT;
1226:     *size   = hexS;
1227:     *cone   = hexC;
1228:     *ornt   = hexO;
1229:     break;
1230:   case DM_POLYTOPE_TRI_PRISM:
1231:     *Nt     = 4;
1232:     *target = tripT;
1233:     *size   = tripS;
1234:     *cone   = tripC;
1235:     *ornt   = tripO;
1236:     break;
1237:   case DM_POLYTOPE_TRI_PRISM_TENSOR:
1238:     *Nt     = 2;
1239:     *target = ttriT;
1240:     *size   = ttriS;
1241:     *cone   = ttriC;
1242:     *ornt   = ttriO;
1243:     break;
1244:   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
1245:     *Nt     = 3;
1246:     *target = tquadT;
1247:     *size   = tquadS;
1248:     *cone   = tquadC;
1249:     *ornt   = tquadO;
1250:     break;
1251:   case DM_POLYTOPE_PYRAMID:
1252:     *Nt     = 5;
1253:     *target = tpyrT;
1254:     *size   = tpyrS;
1255:     *cone   = tpyrC;
1256:     *ornt   = tpyrO;
1257:     break;
1258:   case DM_POLYTOPE_FV_GHOST:
1259:     *Nt     = 0;
1260:     *target = NULL;
1261:     *size   = NULL;
1262:     *cone   = NULL;
1263:     *ornt   = NULL;
1264:     break;
1265:   default:
1266:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1267:   }
1268:   PetscFunctionReturn(PETSC_SUCCESS);
1269: }

1271: static PetscErrorCode DMPlexTransformInitialize_Regular(DMPlexTransform tr)
1272: {
1273:   PetscFunctionBegin;
1274:   tr->ops->view                  = DMPlexTransformView_Regular;
1275:   tr->ops->setup                 = DMPlexTransformSetUp_Regular;
1276:   tr->ops->destroy               = DMPlexTransformDestroy_Regular;
1277:   tr->ops->setdimensions         = DMPlexTransformSetDimensions_Internal;
1278:   tr->ops->celltransform         = DMPlexTransformCellRefine_Regular;
1279:   tr->ops->getsubcellorientation = DMPlexTransformGetSubcellOrientation_Regular;
1280:   tr->ops->mapcoordinates        = DMPlexTransformMapCoordinatesBarycenter_Internal;
1281:   PetscFunctionReturn(PETSC_SUCCESS);
1282: }

1284: PETSC_EXTERN PetscErrorCode DMPlexTransformCreate_Regular(DMPlexTransform tr)
1285: {
1286:   DMPlexRefine_Regular *f;

1288:   PetscFunctionBegin;
1290:   PetscCall(PetscNew(&f));
1291:   tr->data = f;

1293:   PetscCall(DMPlexTransformInitialize_Regular(tr));
1294:   PetscFunctionReturn(PETSC_SUCCESS);
1295: }