xref: /petsc/src/dm/impls/plex/transform/impls/refine/regular/plexrefregular.c (revision 6a5217c03994f2d95bb2e6dbd8bed42381aeb015)
1 #include <petsc/private/dmplextransformimpl.h> /*I "petscdmplextransform.h" I*/
2 
3 /* Regular Refinment of Hybrid Meshes
4 
5    We would like to express regular refinement as a small set of rules that can be applied on every point of the Plex
6    to automatically generate a refined Plex. In fact, we would like these rules to be general enough to encompass other
7    transformations, such as changing from one type of cell to another, as simplex to hex.
8 
9    To start, we can create a function that takes an original cell type and returns the number of new cells replacing it
10    and the types of the new cells.
11 
12    We need the group multiplication table for group actions from the dihedral group for each cell type.
13 
14    We need an operator which takes in a cell, and produces a new set of cells with new faces and correct orientations. I think
15    we can just write this operator for faces with identity, and then compose the face orientation actions to get the actual
16    (face, orient) pairs for each subcell.
17 */
18 
19 /*@
20   DMPlexRefineRegularGetAffineFaceTransforms - Gets the affine map from the reference face cell to each face in the given cell
21 
22   Input Parameters:
23 + cr - The DMPlexCellRefiner object
24 - ct - The cell type
25 
26   Output Parameters:
27 + Nf   - The number of faces for this cell type
28 . v0   - The translation of the first vertex for each face
29 . J    - The Jacobian for each face (map from original cell to subcell)
30 . invJ - The inverse Jacobian for each face
31 - detJ - The determinant of the Jacobian for each face
32 
33   Note: The Jacobian and inverse Jacboian will be rectangular, and the inverse is really a generalized inverse.
34 $         v0 + j x_face = x_cell
35 $    invj (x_cell - v0) = x_face
36 
37   Level: developer
38 
39 .seealso: DMPlexCellRefinerGetAffineTransforms(), Create()
40 @*/
41 PetscErrorCode DMPlexRefineRegularGetAffineFaceTransforms(DMPlexTransform tr, DMPolytopeType ct, PetscInt *Nf, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[], PetscReal *detJ[])
42 {
43   /*
44    2
45    |\
46    | \
47    |  \
48    |   \
49    |    \
50    |     \
51    |      \
52    2       1
53    |        \
54    |         \
55    |          \
56    0---0-------1
57    v0[Nf][dc]:       3 x 2
58    J[Nf][df][dc]:    3 x 1 x 2
59    invJ[Nf][dc][df]: 3 x 2 x 1
60    detJ[Nf]:         3
61    */
62   static PetscReal tri_v0[]   = {0.0, -1.0,  0.0, 0.0,  -1.0,  0.0};
63   static PetscReal tri_J[]    = {1.0, 0.0,  -1.0, 1.0,   0.0, -1.0};
64   static PetscReal tri_invJ[] = {1.0, 0.0,  -0.5, 0.5,   0.0, -1.0};
65   static PetscReal tri_detJ[] = {1.0,  1.414213562373095,  1.0};
66   /*
67    3---------2---------2
68    |                   |
69    |                   |
70    |                   |
71    3                   1
72    |                   |
73    |                   |
74    |                   |
75    0---------0---------1
76 
77    v0[Nf][dc]:       4 x 2
78    J[Nf][df][dc]:    4 x 1 x 2
79    invJ[Nf][dc][df]: 4 x 2 x 1
80    detJ[Nf]:         4
81    */
82   static PetscReal quad_v0[]   = {0.0, -1.0,  1.0, 0.0,   0.0, 1.0  -1.0,  0.0};
83   static PetscReal quad_J[]    = {1.0, 0.0,   0.0, 1.0,  -1.0, 0.0,  0.0, -1.0};
84   static PetscReal quad_invJ[] = {1.0, 0.0,   0.0, 1.0,  -1.0, 0.0,  0.0, -1.0};
85   static PetscReal quad_detJ[] = {1.0,  1.0,  1.0,  1.0};
86 
87   PetscFunctionBegin;
88   switch (ct) {
89     case DM_POLYTOPE_TRIANGLE:      if (Nf) *Nf = 3; if (v0) *v0 = tri_v0;  if (J) *J = tri_J;  if (invJ) *invJ = tri_invJ;  if (detJ) *detJ = tri_detJ;  break;
90     case DM_POLYTOPE_QUADRILATERAL: if (Nf) *Nf = 4; if (v0) *v0 = quad_v0; if (J) *J = quad_J; if (invJ) *invJ = quad_invJ; if (detJ) *detJ = quad_detJ; break;
91     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
92   }
93   PetscFunctionReturn(0);
94 }
95 
96 /*@
97   DMPlexRefineRegularGetAffineTransforms - Gets the affine map from the reference cell to each subcell
98 
99   Input Parameters:
100 + cr - The DMPlexCellRefiner object
101 - ct - The cell type
102 
103   Output Parameters:
104 + Nc   - The number of subcells produced from this cell type
105 . v0   - The translation of the first vertex for each subcell
106 . J    - The Jacobian for each subcell (map from reference cell to subcell)
107 - invJ - The inverse Jacobian for each subcell
108 
109   Level: developer
110 
111 .seealso: DMPlexRefineRegularGetAffineFaceTransforms(), DMPLEXREFINEREGULAR
112 @*/
113 PetscErrorCode DMPlexRefineRegularGetAffineTransforms(DMPlexTransform tr, DMPolytopeType ct, PetscInt *Nc, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[])
114 {
115   /*
116    2
117    |\
118    | \
119    |  \
120    |   \
121    | C  \
122    |     \
123    |      \
124    2---1---1
125    |\  D  / \
126    | 2   0   \
127    |A \ /  B  \
128    0---0-------1
129    */
130   static PetscReal tri_v0[]   = {-1.0, -1.0,  0.0, -1.0,  -1.0, 0.0,  0.0, -1.0};
131   static PetscReal tri_J[]    = {0.5, 0.0,
132                                  0.0, 0.5,
133 
134                                  0.5, 0.0,
135                                  0.0, 0.5,
136 
137                                  0.5, 0.0,
138                                  0.0, 0.5,
139 
140                                  0.0, -0.5,
141                                  0.5,  0.5};
142   static PetscReal tri_invJ[] = {2.0, 0.0,
143                                  0.0, 2.0,
144 
145                                  2.0, 0.0,
146                                  0.0, 2.0,
147 
148                                  2.0, 0.0,
149                                  0.0, 2.0,
150 
151                                  2.0,  2.0,
152                                 -2.0,  0.0};
153     /*
154      3---------2---------2
155      |         |         |
156      |    D    2    C    |
157      |         |         |
158      3----3----0----1----1
159      |         |         |
160      |    A    0    B    |
161      |         |         |
162      0---------0---------1
163      */
164   static PetscReal quad_v0[]   = {-1.0, -1.0,  0.0, -1.0,  0.0, 0.0,  -1.0, 0.0};
165   static PetscReal quad_J[]    = {0.5, 0.0,
166                                   0.0, 0.5,
167 
168                                   0.5, 0.0,
169                                   0.0, 0.5,
170 
171                                   0.5, 0.0,
172                                   0.0, 0.5,
173 
174                                   0.5, 0.0,
175                                   0.0, 0.5};
176   static PetscReal quad_invJ[] = {2.0, 0.0,
177                                   0.0, 2.0,
178 
179                                   2.0, 0.0,
180                                   0.0, 2.0,
181 
182                                   2.0, 0.0,
183                                   0.0, 2.0,
184 
185                                   2.0, 0.0,
186                                   0.0, 2.0};
187     /*
188      Bottom (viewed from top)    Top
189      1---------2---------2       7---------2---------6
190      |         |         |       |         |         |
191      |    B    2    C    |       |    H    2    G    |
192      |         |         |       |         |         |
193      3----3----0----1----1       3----3----0----1----1
194      |         |         |       |         |         |
195      |    A    0    D    |       |    E    0    F    |
196      |         |         |       |         |         |
197      0---------0---------3       4---------0---------5
198      */
199   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,
200                                  -1.0, -1.0,  0.0,   0.0, -1.0,  0.0,  0.0, 0.0,  0.0,  -1.0,  0.0,  0.0};
201   static PetscReal hex_J[]    = {0.5, 0.0, 0.0,
202                                  0.0, 0.5, 0.0,
203                                  0.0, 0.0, 0.5,
204 
205                                  0.5, 0.0, 0.0,
206                                  0.0, 0.5, 0.0,
207                                  0.0, 0.0, 0.5,
208 
209                                  0.5, 0.0, 0.0,
210                                  0.0, 0.5, 0.0,
211                                  0.0, 0.0, 0.5,
212 
213                                  0.5, 0.0, 0.0,
214                                  0.0, 0.5, 0.0,
215                                  0.0, 0.0, 0.5,
216 
217                                  0.5, 0.0, 0.0,
218                                  0.0, 0.5, 0.0,
219                                  0.0, 0.0, 0.5,
220 
221                                  0.5, 0.0, 0.0,
222                                  0.0, 0.5, 0.0,
223                                  0.0, 0.0, 0.5,
224 
225                                  0.5, 0.0, 0.0,
226                                  0.0, 0.5, 0.0,
227                                  0.0, 0.0, 0.5,
228 
229                                  0.5, 0.0, 0.0,
230                                  0.0, 0.5, 0.0,
231                                  0.0, 0.0, 0.5};
232   static PetscReal hex_invJ[] = {2.0, 0.0, 0.0,
233                                  0.0, 2.0, 0.0,
234                                  0.0, 0.0, 2.0,
235 
236                                  2.0, 0.0, 0.0,
237                                  0.0, 2.0, 0.0,
238                                  0.0, 0.0, 2.0,
239 
240                                  2.0, 0.0, 0.0,
241                                  0.0, 2.0, 0.0,
242                                  0.0, 0.0, 2.0,
243 
244                                  2.0, 0.0, 0.0,
245                                  0.0, 2.0, 0.0,
246                                  0.0, 0.0, 2.0,
247 
248                                  2.0, 0.0, 0.0,
249                                  0.0, 2.0, 0.0,
250                                  0.0, 0.0, 2.0,
251 
252                                  2.0, 0.0, 0.0,
253                                  0.0, 2.0, 0.0,
254                                  0.0, 0.0, 2.0,
255 
256                                  2.0, 0.0, 0.0,
257                                  0.0, 2.0, 0.0,
258                                  0.0, 0.0, 2.0,
259 
260                                  2.0, 0.0, 0.0,
261                                  0.0, 2.0, 0.0,
262                                  0.0, 0.0, 2.0};
263 
264   PetscFunctionBegin;
265   switch (ct) {
266     case DM_POLYTOPE_TRIANGLE:      if (Nc) *Nc = 4; if (v0) *v0 = tri_v0;  if (J) *J = tri_J;  if (invJ) *invJ = tri_invJ;  break;
267     case DM_POLYTOPE_QUADRILATERAL: if (Nc) *Nc = 4; if (v0) *v0 = quad_v0; if (J) *J = quad_J; if (invJ) *invJ = quad_invJ; break;
268     case DM_POLYTOPE_HEXAHEDRON:    if (Nc) *Nc = 8; if (v0) *v0 = hex_v0;  if (J) *J = hex_J;  if (invJ) *invJ = hex_invJ;  break;
269     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
270   }
271   PetscFunctionReturn(0);
272 }
273 
274 #if 0
275 static PetscErrorCode DMPlexCellRefinerGetCellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
276 {
277   static PetscReal seg_v[]  = {-1.0,  0.0,  1.0};
278   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};
279   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};
280   static PetscReal tet_v[]  = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
281                                -1.0,  0.0, -1.0,   0.0,  0.0, -1.0,  -1.0,  1.0, -1.0,
282                                -1.0, -1.0,  0.0,   0.0, -1.0,  0.0,  -1.0,  0.0,  0.0,  -1.0, -1.0,  1.0};
283   static PetscReal hex_v[]  = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
284                                -1.0,  0.0, -1.0,   0.0,  0.0, -1.0,   1.0,  0.0, -1.0,
285                                -1.0,  1.0, -1.0,   0.0,  1.0, -1.0,   1.0,  1.0, -1.0,
286                                -1.0, -1.0,  0.0,   0.0, -1.0,  0.0,   1.0, -1.0,  0.0,
287                                -1.0,  0.0,  0.0,   0.0,  0.0,  0.0,   1.0,  0.0,  0.0,
288                                -1.0,  1.0,  0.0,   0.0,  1.0,  0.0,   1.0,  1.0,  0.0,
289                                -1.0, -1.0,  1.0,   0.0, -1.0,  1.0,   1.0, -1.0,  1.0,
290                                -1.0,  0.0,  1.0,   0.0,  0.0,  1.0,   1.0,  0.0,  1.0,
291                                -1.0,  1.0,  1.0,   0.0,  1.0,  1.0,   1.0,  1.0,  1.0};
292 
293   PetscFunctionBegin;
294   switch (ct) {
295     case DM_POLYTOPE_SEGMENT:       *Nv =  3; *subcellV = seg_v;  break;
296     case DM_POLYTOPE_TRIANGLE:      *Nv =  6; *subcellV = tri_v;  break;
297     case DM_POLYTOPE_QUADRILATERAL: *Nv =  9; *subcellV = quad_v; break;
298     case DM_POLYTOPE_TETRAHEDRON:   *Nv = 10; *subcellV = tet_v;  break;
299     case DM_POLYTOPE_HEXAHEDRON:    *Nv = 27; *subcellV = hex_v;  break;
300     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
301   }
302   PetscFunctionReturn(0);
303 }
304 
305 static PetscErrorCode DMPlexCellRefinerGetSubcellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
306 {
307   static PetscInt seg_v[]  = {0, 1, 1, 2};
308   static PetscInt tri_v[]  = {0, 3, 5,  3, 1, 4,  5, 4, 2,  3, 4, 5};
309   static PetscInt quad_v[] = {0, 4, 8, 7,  4, 1, 5, 8,  8, 5, 2, 6,  7, 8, 6, 3};
310   static PetscInt tet_v[]  = {0, 3, 1, 6,  3, 2, 4, 8,  1, 4, 5, 7,  6, 8, 7, 9,
311                               1, 6, 3, 7,  8, 4, 3, 7,  7, 3, 1, 4,  7, 3, 8, 6};
312   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,
313                               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};
314 
315   PetscFunctionBegin;
316   PetscCheck(ct == rct,PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]);
317   switch (ct) {
318     case DM_POLYTOPE_SEGMENT:       *Nv = 2; *subcellV = &seg_v[r*(*Nv)];  break;
319     case DM_POLYTOPE_TRIANGLE:      *Nv = 3; *subcellV = &tri_v[r*(*Nv)];  break;
320     case DM_POLYTOPE_QUADRILATERAL: *Nv = 4; *subcellV = &quad_v[r*(*Nv)]; break;
321     case DM_POLYTOPE_TETRAHEDRON:   *Nv = 4; *subcellV = &tet_v[r*(*Nv)];  break;
322     case DM_POLYTOPE_HEXAHEDRON:    *Nv = 8; *subcellV = &hex_v[r*(*Nv)];  break;
323     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
324   }
325   PetscFunctionReturn(0);
326 }
327 #endif
328 
329 static PetscErrorCode DMPlexTransformView_Regular(DMPlexTransform tr, PetscViewer viewer)
330 {
331   PetscBool      isascii;
332 
333   PetscFunctionBegin;
334   PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1);
335   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
336   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii));
337   if (isascii) {
338     const char *name;
339 
340     PetscCall(PetscObjectGetName((PetscObject) tr, &name));
341     PetscCall(PetscViewerASCIIPrintf(viewer, "Regular refinement %s\n", name ? name : ""));
342   } else {
343     SETERRQ(PetscObjectComm((PetscObject) tr), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlexTransform writing", ((PetscObject) viewer)->type_name);
344   }
345   PetscFunctionReturn(0);
346 }
347 
348 static PetscErrorCode DMPlexTransformSetUp_Regular(DMPlexTransform tr)
349 {
350   PetscFunctionBegin;
351   PetscFunctionReturn(0);
352 }
353 
354 static PetscErrorCode DMPlexTransformDestroy_Regular(DMPlexTransform tr)
355 {
356   DMPlexRefine_Regular *f = (DMPlexRefine_Regular *) tr->data;
357 
358   PetscFunctionBegin;
359   PetscCall(PetscFree(f));
360   PetscFunctionReturn(0);
361 }
362 
363 PetscErrorCode DMPlexTransformGetSubcellOrientation_Regular(DMPlexTransform tr, DMPolytopeType sct, PetscInt sp, PetscInt so, DMPolytopeType tct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
364 {
365   static PetscInt seg_seg[] = {1, -1, 0, -1,
366                                0,  0, 1,  0};
367   static PetscInt tri_seg[] = {2, -1, 1, -1, 0, -1,
368                                1, -1, 0, -1, 2, -1,
369                                0, -1, 2, -1, 1, -1,
370                                0,  0, 1,  0, 2,  0,
371                                1,  0, 2,  0, 0,  0,
372                                2,  0, 0,  0, 1,  0};
373   static PetscInt tri_tri[] = {1, -3, 0, -3, 2, -3, 3, -2,
374                                0, -2, 2, -2, 1, -2, 3, -1,
375                                2, -1, 1, -1, 0, -1, 3, -3,
376                                0,  0, 1,  0, 2,  0, 3,  0,
377                                1,  1, 2,  1, 0,  1, 3,  1,
378                                2,  2, 0,  2, 1,  2, 3,  2};
379   static PetscInt quad_seg[]  = {1, 0, 0, 0, 3, 0, 2, 0,
380                                  0, 0, 3, 0, 2, 0, 1, 0,
381                                  3, 0, 2, 0, 1, 0, 0, 0,
382                                  2, 0, 1, 0, 0, 0, 3, 0,
383                                  0, 0, 1, 0, 2, 0, 3, 0,
384                                  1, 0, 2, 0, 3, 0, 0, 0,
385                                  2, 0, 3, 0, 0, 0, 1, 0,
386                                  3, 0, 0, 0, 1, 0, 2, 0};
387   static PetscInt quad_quad[] = {2, -4, 1, -4, 0, -4, 3, -4,
388                                  1, -3, 0, -3, 3, -3, 2, -3,
389                                  0, -2, 3, -2, 2, -2, 1, -2,
390                                  3, -1, 2, -1, 1, -1, 0, -1,
391                                  0,  0, 1,  0, 2,  0, 3,  0,
392                                  1,  1, 2,  1, 3,  1, 0,  1,
393                                  2,  2, 3,  2, 0,  2, 1,  2,
394                                  3,  3, 0,  3, 1,  3, 2,  3};
395   static PetscInt tseg_seg[]  = {0, -1,
396                                  0,  0,
397                                  0,  0,
398                                  0, -1};
399   static PetscInt tseg_tseg[] = {1, -2, 0, -2,
400                                  1, -1, 0, -1,
401                                  0,  0, 1,  0,
402                                  0,  1, 1,  1};
403   static PetscInt tet_seg[]   = {0, -1,
404                                  0,  0,
405                                  0,  0,
406                                  0, -1,
407                                  0,  0,
408                                  0,  0,
409                                  0,  0,
410                                  0,  0,
411                                  0,  0,
412                                  0,  0,
413                                  0,  0,
414                                  0,  0,
415                                  0,  0,
416                                  0,  0,
417                                  0,  0,
418                                  0,  0,
419                                  0,  0,
420                                  0,  0,
421                                  0, -1,
422                                  0,  0,
423                                  0,  0,
424                                  0, -1,
425                                  0,  0,
426                                  0,  0};
427   static PetscInt tet_tri[]   = {2, -1, 3, -1, 1, -3, 0, -2, 6, 1, 7, -3, 5, 2, 4, -3,
428                                  3, -1, 1, -1, 2, -3, 0, -1, 4, 0, 5, 0, 6, 0, 7, 0,
429                                  1, -1, 2, -1, 3, -3, 0, -3, 4, 0, 5, 0, 6, 0, 7, 0,
430                                  3, -2, 2, -3, 0, -1, 1, -1, 7, -3, 6, 1, 4, 2, 5, -3,
431                                  2, -3, 0, -2, 3, -1, 1, -3, 4, 0, 5, 0, 6, 0, 7, 0,
432                                  0, -2, 3, -2, 2, -2, 1, -2, 4, 0, 5, 0, 6, 0, 7, 0,
433                                  0, -1, 1, -2, 3, -2, 2, -2, 7, 1, 6, -3, 5, -3, 4, 2,
434                                  1, -2, 3, -3, 0, -3, 2, -1, 4, 0, 5, 0, 6, 0, 7, 0,
435                                  3, -3, 0, -1, 1, -1, 2, -3, 4, 0, 5, 0, 6, 0, 7, 0,
436                                  1, -3, 0, -3, 2, -1, 3, -3, 6, -3, 7, 1, 4, -3, 5, 2,
437                                  0, -3, 2, -2, 1, -2, 3, -2, 4, 0, 5, 0, 6, 0, 7, 0,
438                                  2, -2, 1, -3, 0, -2, 3, -1, 4, 0, 5, 0, 6, 0, 7, 0,
439                                  0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0,
440                                  1, 0, 2, 2, 0, 1, 3, 1, 4, 0, 5, 0, 6, 0, 7, 0,
441                                  2, 2, 0, 0, 1, 1, 3, 2, 4, 0, 5, 0, 6, 0, 7, 0,
442                                  1, 2, 0, 1, 3, 1, 2, 2, 5, 0, 4, 0, 7, -1, 6, -1,
443                                  0, 1, 3, 0, 1, 0, 2, 0, 4, 0, 5, 0, 6, 0, 7, 0,
444                                  3, 0, 1, 2, 0, 2, 2, 1, 4, 0, 5, 0, 6, 0, 7, 0,
445                                  2, 0, 3, 2, 0, 0, 1, 1, 4, -2, 5, -2, 7, 0, 6, 0,
446                                  3, 2, 0, 2, 2, 1, 1, 2, 4, 0, 5, 0, 6, 0, 7, 0,
447                                  0, 2, 2, 0, 3, 0, 1, 0, 4, 0, 5, 0, 6, 0, 7, 0,
448                                  3, 1, 2, 1, 1, 2, 0, 2, 5, -2, 4, -2, 6, -1, 7, -1,
449                                  2, 1, 1, 1, 3, 2, 0, 0, 4, 0, 5, 0, 6, 0, 7, 0,
450                                  1, 1, 3, 1, 2, 2, 0, 1, 4, 0, 5, 0, 6, 0, 7, 0};
451   static PetscInt tet_tet[]   = {2, -12, 3, -12, 1, -12, 0, -12, 6, -9, 7, -9, 5, -12, 4, -12,
452                                  3, -11, 1, -11, 2, -11, 0, -11, 4, 0, 5, 0, 6, 0, 7, 0,
453                                  1, -10, 2, -10, 3, -10, 0, -10, 4, 0, 5, 0, 6, 0, 7, 0,
454                                  3, -9, 2, -9, 0, -9, 1, -9, 7, -9, 6, -9, 4, -12, 5, -12,
455                                  2, -8, 0, -8, 3, -8, 1, -8, 4, 0, 5, 0, 6, 0, 7, 0,
456                                  0, -7, 3, -7, 2, -7, 1, -7, 4, 0, 5, 0, 6, 0, 7, 0,
457                                  0, -6, 1, -6, 3, -6, 2, -6, 4, -3, 5, -3, 7, -6, 6, -6,
458                                  1, -5, 3, -5, 0, -5, 2, -5, 4, 0, 5, 0, 6, 0, 7, 0,
459                                  3, -4, 0, -4, 1, -4, 2, -4, 4, 0, 5, 0, 6, 0, 7, 0,
460                                  1, -3, 0, -3, 2, -3, 3, -3, 5, -3, 4, -3, 6, -6, 7, -6,
461                                  0, -2, 2, -2, 1, -2, 3, -2, 4, 0, 5, 0, 6, 0, 7, 0,
462                                  2, -1, 1, -1, 0, -1, 3, -1, 4, 0, 5, 0, 6, 0, 7, 0,
463                                  0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0,
464                                  1, 1, 2, 1, 0, 1, 3, 1, 4, 0, 5, 0, 6, 0, 7, 0,
465                                  2, 2, 0, 2, 1, 2, 3, 2, 4, 0, 5, 0, 6, 0, 7, 0,
466                                  1, 3, 0, 3, 3, 3, 2, 3, 5, 0, 4, 0, 7, 0, 6, 0,
467                                  0, 4, 3, 4, 1, 4, 2, 4, 4, 0, 5, 0, 6, 0, 7, 0,
468                                  3, 5, 1, 5, 0, 5, 2, 5, 4, 0, 5, 0, 6, 0, 7, 0,
469                                  2, 6, 3, 6, 0, 6, 1, 6, 6, 6, 7, 6, 4, 6, 5, 6,
470                                  3, 7, 0, 7, 2, 7, 1, 7, 4, 0, 5, 0, 6, 0, 7, 0,
471                                  0, 8, 2, 8, 3, 8, 1, 8, 4, 0, 5, 0, 6, 0, 7, 0,
472                                  3, 9, 2, 9, 1, 9, 0, 9, 7, 6, 6, 6, 5, 6, 4, 6,
473                                  2, 10, 1, 10, 3, 10, 0, 10, 4, 0, 5, 0, 6, 0, 7, 0,
474                                  1, 11, 3, 11, 2, 11, 0, 11, 4, 0, 5, 0, 6, 0, 7, 0};
475   static PetscInt hex_seg[]   = {2, 0, 3, 0, 4, 0, 5, 0, 1, 0, 0, 0,
476                                  4, 0, 5, 0, 0, 0, 1, 0, 3, 0, 2, 0,
477                                  5, 0, 4, 0, 1, 0, 0, 0, 3, 0, 2, 0,
478                                  3, 0, 2, 0, 4, 0, 5, 0, 0, 0, 1, 0,
479                                  3, 0, 2, 0, 5, 0, 4, 0, 1, 0, 0, 0,
480                                  4, 0, 5, 0, 1, 0, 0, 0, 2, 0, 3, 0,
481                                  2, 0, 3, 0, 5, 0, 4, 0, 0, 0, 1, 0,
482                                  5, 0, 4, 0, 0, 0, 1, 0, 2, 0, 3, 0,
483                                  4, 0, 5, 0, 3, 0, 2, 0, 1, 0, 0, 0,
484                                  5, 0, 4, 0, 3, 0, 2, 0, 0, 0, 1, 0,
485                                  3, 0, 2, 0, 1, 0, 0, 0, 4, 0, 5, 0,
486                                  2, 0, 3, 0, 0, 0, 1, 0, 4, 0, 5, 0,
487                                  1, 0, 0, 0, 4, 0, 5, 0, 3, 0, 2, 0,
488                                  1, 0, 0, 0, 5, 0, 4, 0, 2, 0, 3, 0,
489                                  5, 0, 4, 0, 2, 0, 3, 0, 1, 0, 0, 0,
490                                  1, 0, 0, 0, 2, 0, 3, 0, 4, 0, 5, 0,
491                                  4, 0, 5, 0, 2, 0, 3, 0, 0, 0, 1, 0,
492                                  3, 0, 2, 0, 0, 0, 1, 0, 5, 0, 4, 0,
493                                  1, 0, 0, 0, 3, 0, 2, 0, 5, 0, 4, 0,
494                                  2, 0, 3, 0, 1, 0, 0, 0, 5, 0, 4, 0,
495                                  0, 0, 1, 0, 4, 0, 5, 0, 2, 0, 3, 0,
496                                  0, 0, 1, 0, 3, 0, 2, 0, 4, 0, 5, 0,
497                                  0, 0, 1, 0, 5, 0, 4, 0, 3, 0, 2, 0,
498                                  0, 0, 1, 0, 2, 0, 3, 0, 5, 0, 4, 0,
499                                  0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0,
500                                  0, 0, 1, 0, 5, 0, 4, 0, 2, 0, 3, 0,
501                                  0, 0, 1, 0, 3, 0, 2, 0, 5, 0, 4, 0,
502                                  0, 0, 1, 0, 4, 0, 5, 0, 3, 0, 2, 0,
503                                  2, 0, 3, 0, 1, 0, 0, 0, 4, 0, 5, 0,
504                                  1, 0, 0, 0, 3, 0, 2, 0, 4, 0, 5, 0,
505                                  3, 0, 2, 0, 0, 0, 1, 0, 4, 0, 5, 0,
506                                  4, 0, 5, 0, 2, 0, 3, 0, 1, 0, 0, 0,
507                                  1, 0, 0, 0, 2, 0, 3, 0, 5, 0, 4, 0,
508                                  5, 0, 4, 0, 2, 0, 3, 0, 0, 0, 1, 0,
509                                  1, 0, 0, 0, 5, 0, 4, 0, 3, 0, 2, 0,
510                                  1, 0, 0, 0, 4, 0, 5, 0, 2, 0, 3, 0,
511                                  2, 0, 3, 0, 0, 0, 1, 0, 5, 0, 4, 0,
512                                  3, 0, 2, 0, 1, 0, 0, 0, 5, 0, 4, 0,
513                                  5, 0, 4, 0, 3, 0, 2, 0, 1, 0, 0, 0,
514                                  4, 0, 5, 0, 3, 0, 2, 0, 0, 0, 1, 0,
515                                  5, 0, 4, 0, 0, 0, 1, 0, 3, 0, 2, 0,
516                                  2, 0, 3, 0, 5, 0, 4, 0, 1, 0, 0, 0,
517                                  4, 0, 5, 0, 1, 0, 0, 0, 3, 0, 2, 0,
518                                  3, 0, 2, 0, 5, 0, 4, 0, 0, 0, 1, 0,
519                                  3, 0, 2, 0, 4, 0, 5, 0, 1, 0, 0, 0,
520                                  5, 0, 4, 0, 1, 0, 0, 0, 2, 0, 3, 0,
521                                  4, 0, 5, 0, 0, 0, 1, 0, 2, 0, 3, 0,
522                                  2, 0, 3, 0, 4, 0, 5, 0, 0, 0, 1, 0};
523   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,
524                                  8, -2, 9, -2, 10, -2, 11, -2, 3, -4, 0, -4, 1, -4, 2, -4, 7, 0, 4, 0, 5, 0, 6, 0,
525                                  9, 1, 8, 1, 11, 1, 10, 1, 0, 3, 3, 3, 2, 3, 1, 3, 5, 2, 6, 2, 7, 2, 4, 2,
526                                  6, 3, 5, 3, 4, 3, 7, 3, 10, -1, 9, -1, 8, -1, 11, -1, 2, -4, 3, -4, 0, -4, 1, -4,
527                                  4, 1, 7, 1, 6, 1, 5, 1, 11, 2, 8, 2, 9, 2, 10, 2, 1, 3, 0, 3, 3, 3, 2, 3,
528                                  10, -4, 11, -4, 8, -4, 9, -4, 2, 1, 1, 1, 0, 1, 3, 1, 6, -1, 5, -1, 4, -1, 7, -1,
529                                  5, -4, 6, -4, 7, -4, 4, -4, 9, 0, 10, 0, 11, 0, 8, 0, 0, -2, 1, -2, 2, -2, 3, -2,
530                                  11, 3, 10, 3, 9, 3, 8, 3, 1, -2, 2, -2, 3, -2, 0, -2, 4, -3, 7, -3, 6, -3, 5, -3,
531                                  11, -1, 8, -1, 9, -1, 10, -1, 7, 3, 4, 3, 5, 3, 6, 3, 2, 2, 1, 2, 0, 2, 3, 2,
532                                  10, 2, 9, 2, 8, 2, 11, 2, 5, 1, 6, 1, 7, 1, 4, 1, 1, -1, 2, -1, 3, -1, 0, -1,
533                                  5, 2, 4, 2, 7, 2, 6, 2, 1, 2, 0, 2, 3, 2, 2, 2, 10, -4, 9, -4, 8, -4, 11, -4,
534                                  4, -3, 5, -3, 6, -3, 7, -3, 0, -3, 1, -3, 2, -3, 3, -3, 8, -2, 11, -2, 10, -2, 9, -2,
535                                  3, 1, 0, 1, 1, 1, 2, 1, 9, -4, 8, -4, 11, -4, 10, -4, 6, 3, 7, 3, 4, 3, 5, 3,
536                                  1, 3, 2, 3, 3, 3, 0, 3, 10, 1, 11, 1, 8, 1, 9, 1, 5, -4, 4, -4, 7, -4, 6, -4,
537                                  8, 0, 11, 0, 10, 0, 9, 0, 4, -4, 7, -4, 6, -4, 5, -4, 0, 0, 3, 0, 2, 0, 1, 0,
538                                  0, 0, 1, 0, 2, 0, 3, 0, 5, -1, 4, -1, 7, -1, 6, -1, 9, -3, 8, -3, 11, -3, 10, -3,
539                                  9, -3, 10, -3, 11, -3, 8, -3, 6, -2, 5, -2, 4, -2, 7, -2, 3, -3, 0, -3, 1, -3, 2, -3,
540                                  7, 0, 6, 0, 5, 0, 4, 0, 2, -1, 3, -1, 0, -1, 1, -1, 11, 3, 8, 3, 9, 3, 10, 3,
541                                  2, 2, 3, 2, 0, 2, 1, 2, 6, 2, 7, 2, 4, 2, 5, 2, 10, 2, 11, 2, 8, 2, 9, 2,
542                                  6, -1, 7, -1, 4, -1, 5, -1, 3, 0, 2, 0, 1, 0, 0, 0, 9, 1, 10, 1, 11, 1, 8, 1,
543                                  2, -4, 1, -4, 0, -4, 3, -4, 11, -2, 10, -2, 9, -2, 8, -2, 7, -2, 6, -2, 5, -2, 4, -2,
544                                  1, -1, 0, -1, 3, -1, 2, -1, 4, 0, 5, 0, 6, 0, 7, 0, 11, -1, 10, -1, 9, -1, 8, -1,
545                                  0, -2, 3, -2, 2, -2, 1, -2, 8, 3, 9, 3, 10, 3, 11, 3, 4, 1, 5, 1, 6, 1, 7, 1,
546                                  3, -3, 2, -3, 1, -3, 0, -3, 7, -3, 6, -3, 5, -3, 4, -3, 8, 0, 9, 0, 10, 0, 11, 0,
547                                  0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0,
548                                  1, 3, 2, 3, 3, 3, 0, 3, 11, -2, 10, -2, 9, -2, 8, -2, 4, 1, 5, 1, 6, 1, 7, 1,
549                                  2, 2, 3, 2, 0, 2, 1, 2, 7, -3, 6, -3, 5, -3, 4, -3, 11, -1, 10, -1, 9, -1, 8, -1,
550                                  3, 1, 0, 1, 1, 1, 2, 1, 8, 3, 9, 3, 10, 3, 11, 3, 7, -2, 6, -2, 5, -2, 4, -2,
551                                  5, 2, 4, 2, 7, 2, 6, 2, 0, -3, 1, -3, 2, -3, 3, -3, 9, 1, 10, 1, 11, 1, 8, 1,
552                                  1, -1, 0, -1, 3, -1, 2, -1, 5, -1, 4, -1, 7, -1, 6, -1, 10, 2, 11, 2, 8, 2, 9, 2,
553                                  4, -3, 5, -3, 6, -3, 7, -3, 1, 2, 0, 2, 3, 2, 2, 2, 11, 3, 8, 3, 9, 3, 10, 3,
554                                  8, 0, 11, 0, 10, 0, 9, 0, 7, 3, 4, 3, 5, 3, 6, 3, 3, -3, 0, -3, 1, -3, 2, -3,
555                                  3, -3, 2, -3, 1, -3, 0, -3, 6, 2, 7, 2, 4, 2, 5, 2, 9, -3, 8, -3, 11, -3, 10, -3,
556                                  9, -3, 10, -3, 11, -3, 8, -3, 5, 1, 6, 1, 7, 1, 4, 1, 0, 0, 3, 0, 2, 0, 1, 0,
557                                  0, -2, 3, -2, 2, -2, 1, -2, 9, -4, 8, -4, 11, -4, 10, -4, 5, -4, 4, -4, 7, -4, 6, -4,
558                                  2, -4, 1, -4, 0, -4, 3, -4, 10, 1, 11, 1, 8, 1, 9, 1, 6, 3, 7, 3, 4, 3, 5, 3,
559                                  7, 0, 6, 0, 5, 0, 4, 0, 3, 0, 2, 0, 1, 0, 0, 0, 8, -2, 11, -2, 10, -2, 9, -2,
560                                  6, -1, 7, -1, 4, -1, 5, -1, 2, -1, 3, -1, 0, -1, 1, -1, 10, -4, 9, -4, 8, -4, 11, -4,
561                                  11, -1, 8, -1, 9, -1, 10, -1, 4, -4, 7, -4, 6, -4, 5, -4, 1, -1, 2, -1, 3, -1, 0, -1,
562                                  10, 2, 9, 2, 8, 2, 11, 2, 6, -2, 5, -2, 4, -2, 7, -2, 2, 2, 1, 2, 0, 2, 3, 2,
563                                  8, -2, 9, -2, 10, -2, 11, -2, 0, 3, 3, 3, 2, 3, 1, 3, 4, -3, 7, -3, 6, -3, 5, -3,
564                                  4, 1, 7, 1, 6, 1, 5, 1, 8, -3, 11, -3, 10, -3, 9, -3, 0, -2, 1, -2, 2, -2, 3, -2,
565                                  9, 1, 8, 1, 11, 1, 10, 1, 3, -4, 0, -4, 1, -4, 2, -4, 6, -1, 5, -1, 4, -1, 7, -1,
566                                  5, -4, 6, -4, 7, -4, 4, -4, 10, -1, 9, -1, 8, -1, 11, -1, 1, 3, 0, 3, 3, 3, 2, 3,
567                                  7, -2, 4, -2, 5, -2, 6, -2, 11, 2, 8, 2, 9, 2, 10, 2, 2, -4, 3, -4, 0, -4, 1, -4,
568                                  10, -4, 11, -4, 8, -4, 9, -4, 1, -2, 2, -2, 3, -2, 0, -2, 5, 2, 6, 2, 7, 2, 4, 2,
569                                  11, 3, 10, 3, 9, 3, 8, 3, 2, 1, 1, 1, 0, 1, 3, 1, 7, 0, 4, 0, 5, 0, 6, 0,
570                                  6, 3, 5, 3, 4, 3, 7, 3, 9, 0, 10, 0, 11, 0, 8, 0, 3, 1, 2, 1, 1, 1, 0, 1};
571   static PetscInt hex_hex[]   = {3, -24, 0, -24, 4, -24, 5, -24, 2, -24, 6, -24, 7, -24, 1, -24,
572                                  3, -23, 5, -23, 6, -23, 2, -23, 0, -23, 1, -23, 7, -23, 4, -23,
573                                  4, -22, 0, -22, 1, -22, 7, -22, 5, -22, 6, -22, 2, -22, 3, -22,
574                                  6, -21, 7, -21, 1, -21, 2, -21, 5, -21, 3, -21, 0, -21, 4, -21,
575                                  1, -20, 2, -20, 6, -20, 7, -20, 0, -20, 4, -20, 5, -20, 3, -20,
576                                  6, -19, 2, -19, 3, -19, 5, -19, 7, -19, 4, -19, 0, -19, 1, -19,
577                                  4, -18, 5, -18, 3, -18, 0, -18, 7, -18, 1, -18, 2, -18, 6, -18,
578                                  1, -17, 7, -17, 4, -17, 0, -17, 2, -17, 3, -17, 5, -17, 6, -17,
579                                  2, -16, 3, -16, 5, -16, 6, -16, 1, -16, 7, -16, 4, -16, 0, -16,
580                                  7, -15, 4, -15, 0, -15, 1, -15, 6, -15, 2, -15, 3, -15, 5, -15,
581                                  7, -14, 1, -14, 2, -14, 6, -14, 4, -14, 5, -14, 3, -14, 0, -14,
582                                  0, -13, 4, -13, 5, -13, 3, -13, 1, -13, 2, -13, 6, -13, 7, -13,
583                                  5, -12, 4, -12, 7, -12, 6, -12, 3, -12, 2, -12, 1, -12, 0, -12,
584                                  7, -11, 6, -11, 5, -11, 4, -11, 1, -11, 0, -11, 3, -11, 2, -11,
585                                  0, -10, 1, -10, 7, -10, 4, -10, 3, -10, 5, -10, 6, -10, 2, -10,
586                                  4, -9, 7, -9, 6, -9, 5, -9, 0, -9, 3, -9, 2, -9, 1, -9,
587                                  5, -8, 6, -8, 2, -8, 3, -8, 4, -8, 0, -8, 1, -8, 7, -8,
588                                  2, -7, 6, -7, 7, -7, 1, -7, 3, -7, 0, -7, 4, -7, 5, -7,
589                                  6, -6, 5, -6, 4, -6, 7, -6, 2, -6, 1, -6, 0, -6, 3, -6,
590                                  5, -5, 3, -5, 0, -5, 4, -5, 6, -5, 7, -5, 1, -5, 2, -5,
591                                  2, -4, 1, -4, 0, -4, 3, -4, 6, -4, 5, -4, 4, -4, 7, -4,
592                                  1, -3, 0, -3, 3, -3, 2, -3, 7, -3, 6, -3, 5, -3, 4, -3,
593                                  0, -2, 3, -2, 2, -2, 1, -2, 4, -2, 7, -2, 6, -2, 5, -2,
594                                  3, -1, 2, -1, 1, -1, 0, -1, 5, -1, 4, -1, 7, -1, 6, -1,
595                                  0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0,
596                                  1, 1, 2, 1, 3, 1, 0, 1, 7, 1, 4, 1, 5, 1, 6, 1,
597                                  2, 2, 3, 2, 0, 2, 1, 2, 6, 2, 7, 2, 4, 2, 5, 2,
598                                  3, 3, 0, 3, 1, 3, 2, 3, 5, 3, 6, 3, 7, 3, 4, 3,
599                                  4, 4, 0, 4, 3, 4, 5, 4, 7, 4, 6, 4, 2, 4, 1, 4,
600                                  7, 5, 4, 5, 5, 5, 6, 5, 1, 5, 2, 5, 3, 5, 0, 5,
601                                  1, 6, 7, 6, 6, 6, 2, 6, 0, 6, 3, 6, 5, 6, 4, 6,
602                                  3, 7, 2, 7, 6, 7, 5, 7, 0, 7, 4, 7, 7, 7, 1, 7,
603                                  5, 8, 6, 8, 7, 8, 4, 8, 3, 8, 0, 8, 1, 8, 2, 8,
604                                  4, 9, 7, 9, 1, 9, 0, 9, 5, 9, 3, 9, 2, 9, 6, 9,
605                                  4, 10, 5, 10, 6, 10, 7, 10, 0, 10, 1, 10, 2, 10, 3, 10,
606                                  6, 11, 7, 11, 4, 11, 5, 11, 2, 11, 3, 11, 0, 11, 1, 11,
607                                  3, 12, 5, 12, 4, 12, 0, 12, 2, 12, 1, 12, 7, 12, 6, 12,
608                                  6, 13, 2, 13, 1, 13, 7, 13, 5, 13, 4, 13, 0, 13, 3, 13,
609                                  1, 14, 0, 14, 4, 14, 7, 14, 2, 14, 6, 14, 5, 14, 3, 14,
610                                  6, 15, 5, 15, 3, 15, 2, 15, 7, 15, 1, 15, 0, 15, 4, 15,
611                                  0, 16, 4, 16, 7, 16, 1, 16, 3, 16, 2, 16, 6, 16, 5, 16,
612                                  0, 17, 3, 17, 5, 17, 4, 17, 1, 17, 7, 17, 6, 17, 2, 17,
613                                  5, 18, 3, 18, 2, 18, 6, 18, 4, 18, 7, 18, 1, 18, 0, 18,
614                                  7, 19, 6, 19, 2, 19, 1, 19, 4, 19, 0, 19, 3, 19, 5, 19,
615                                  2, 20, 1, 20, 7, 20, 6, 20, 3, 20, 5, 20, 4, 20, 0, 20,
616                                  7, 21, 1, 21, 0, 21, 4, 21, 6, 21, 5, 21, 3, 21, 2, 21,
617                                  2, 22, 6, 22, 5, 22, 3, 22, 1, 22, 0, 22, 4, 22, 7, 22,
618                                  5, 23, 4, 23, 0, 23, 3, 23, 6, 23, 2, 23, 1, 23, 7, 23};
619   static PetscInt trip_seg[]   = {1,  0, 2,  0, 0,  0,
620                                   2,  0, 0,  0, 1,  0,
621                                   0,  0, 1,  0, 2,  0,
622                                   0, -1, 2, -1, 1, -1,
623                                   1, -1, 0, -1, 2, -1,
624                                   2, -1, 1, -1, 0, -1,
625                                   0,  0, 1,  0, 2,  0,
626                                   2,  0, 0,  0, 1,  0,
627                                   1,  0, 2,  0, 0,  0,
628                                   2, -1, 1, -1, 0, -1,
629                                   1, -1, 0, -1, 2, -1,
630                                   0, -1, 2, -1, 1, -1};
631   static PetscInt trip_tri[]   = {1, 1, 2, 1, 0, 1, 3, 1,
632                                   2, 2, 0, 2, 1, 2, 3, 2,
633                                   0, 0, 1, 0, 2, 0, 3, 0,
634                                   2, -1, 1, -1, 0, -1, 3, -3,
635                                   0, -2, 2, -2, 1, -2, 3, -1,
636                                   1, -3, 0, -3, 2, -3, 3, -2,
637                                   0, 0, 1, 0, 2, 0, 3, 0,
638                                   2, 2, 0, 2, 1, 2, 3, 2,
639                                   1, 1, 2, 1, 0, 1, 3, 1,
640                                   1, -3, 0, -3, 2, -3, 3, -2,
641                                   0, -2, 2, -2, 1, -2, 3, -1,
642                                   2, -1, 1, -1, 0, -1, 3, -3};
643   static PetscInt trip_quad[]  = {4, -1, 5, -1, 3, -1, 1, -1, 2, -1, 0, -1,
644                                   5, -1, 3, -1, 4, -1, 2, -1, 0, -1, 1, -1,
645                                   3, -1, 4, -1, 5, -1, 0, -1, 1, -1, 2, -1,
646                                   0, -3, 2, -3, 1, -3, 3, -3, 5, -3, 4, -3,
647                                   1, -3, 0, -3, 2, -3, 4, -3, 3, -3, 5, -3,
648                                   2, -3, 1, -3, 0, -3, 5, -3, 4, -3, 3, -3,
649                                   0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0,
650                                   2, 0, 0, 0, 1, 0, 5, 0, 3, 0, 4, 0,
651                                   1, 0, 2, 0, 0, 0, 4, 0, 5, 0, 3, 0,
652                                   5, 2, 4, 2, 3, 2, 2, 2, 1, 2, 0, 2,
653                                   4, 2, 3, 2, 5, 2, 1, 2, 0, 2, 2, 2,
654                                   3, 2, 5, 2, 4, 2, 0, 2, 2, 2, 1, 2};
655   static PetscInt trip_trip[]  = {5, -6, 6, -6, 4, -6, 7, -6, 1, -6, 2, -6, 0, -6, 3, -6,
656                                   6, -5, 4, -5, 5, -5, 7, -5, 2, -5, 0, -5, 1, -5, 3, -5,
657                                   4, -4, 5, -4, 6, -4, 7, -4, 0, -4, 1, -4, 2, -4, 3, -4,
658                                   2, -3, 1, -3, 0, -3, 3, -1, 6, -3, 5, -3, 4, -3, 7, -1,
659                                   0, -2, 2, -2, 1, -2, 3, -3, 4, -2, 6, -2, 5, -2, 7, -3,
660                                   1, -1, 0, -1, 2, -1, 3, -2, 5, -1, 4, -1, 6, -1, 7, -2,
661                                   0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0,
662                                   2, 1, 0, 1, 1, 1, 3, 1, 6, 1, 4, 1, 5, 1, 7, 1,
663                                   1, 2, 2, 2, 0, 2, 3, 2, 5, 2, 6, 2, 4, 2, 7, 2,
664                                   5, 3, 4, 3, 6, 3, 7, 4, 1, 3, 0, 3, 2, 3, 3, 4,
665                                   4, 4, 6, 4, 5, 4, 7, 5, 0, 4, 2, 4, 1, 4, 3, 5,
666                                   6, 5, 5, 5, 4, 5, 7, 3, 2, 5, 1, 5, 0, 5, 3, 3};
667   static PetscInt ttri_tseg[]  = {2, -2, 1, -2, 0, -2,
668                                   1, -2, 0, -2, 2, -2,
669                                   0, -2, 2, -2, 1, -2,
670                                   2, -1, 1, -1, 0, -1,
671                                   1, -1, 0, -1, 2, -1,
672                                   0, -1, 2, -1, 1, -1,
673                                   0, 0, 1, 0, 2, 0,
674                                   1, 0, 2, 0, 0, 0,
675                                   2, 0, 0, 0, 1, 0,
676                                   0, 1, 1, 1, 2, 1,
677                                   1, 1, 2, 1, 0, 1,
678                                   2, 1, 0, 1, 1, 1};
679   static PetscInt ttri_ttri[]  = {1, -6, 0, -6, 2, -6, 3, -5,
680                                   0, -5, 2, -5, 1, -5, 3, -4,
681                                   2, -4, 1, -4, 0, -4, 3, -6,
682                                   1, -3, 0, -3, 2, -3, 3, -2,
683                                   0, -2, 2, -2, 1, -2, 3, -1,
684                                   2, -1, 1, -1, 0, -1, 3, -3,
685                                   0, 0, 1, 0, 2, 0, 3, 0,
686                                   1, 1, 2, 1, 0, 1, 3, 1,
687                                   2, 2, 0, 2, 1, 2, 3, 2,
688                                   0, 3, 1, 3, 2, 3, 3, 3,
689                                   1, 4, 2, 4, 0, 4, 3, 4,
690                                   2, 5, 0, 5, 1, 5, 3, 5};
691   static PetscInt tquad_tvert[]  = {0, -1,
692                                     0, -1,
693                                     0, -1,
694                                     0, -1,
695                                     0,  0,
696                                     0,  0,
697                                     0,  0,
698                                     0,  0,
699                                     0,  0,
700                                     0,  0,
701                                     0,  0,
702                                     0,  0,
703                                     0, -1,
704                                     0, -1,
705                                     0, -1,
706                                     0, -1};
707   static PetscInt tquad_tseg[]   = {1, 1, 0, 1, 3, 1, 2, 1,
708                                     0, 1, 3, 1, 2, 1, 1, 1,
709                                     3, 1, 2, 1, 1, 1, 0, 1,
710                                     2, 1, 1, 1, 0, 1, 3, 1,
711                                     1, 0, 0, 0, 3, 0, 2, 0,
712                                     0, 0, 3, 0, 2, 0, 1, 0,
713                                     3, 0, 2, 0, 1, 0, 0, 0,
714                                     2, 0, 1, 0, 0, 0, 3, 0,
715                                     0, 0, 1, 0, 2, 0, 3, 0,
716                                     1, 0, 2, 0, 3, 0, 0, 0,
717                                     2, 0, 3, 0, 0, 0, 1, 0,
718                                     3, 0, 0, 0, 1, 0, 2, 0,
719                                     0, 1, 1, 1, 2, 1, 3, 1,
720                                     1, 1, 2, 1, 3, 1, 0, 1,
721                                     2, 1, 3, 1, 0, 1, 1, 1,
722                                     3, 1, 0, 1, 1, 1, 2, 1};
723   static PetscInt tquad_tquad[]  = {2, -8, 1, -8, 0, -8, 3, -8,
724                                     1, -7, 0, -7, 3, -7, 2, -7,
725                                     0, -6, 3, -6, 2, -6, 1, -6,
726                                     3, -5, 2, -5, 1, -5, 0, -5,
727                                     2, -4, 1, -4, 0, -4, 3, -4,
728                                     1, -3, 0, -3, 3, -3, 2, -3,
729                                     0, -2, 3, -2, 2, -2, 1, -2,
730                                     3, -1, 2, -1, 1, -1, 0, -1,
731                                     0, 0, 1, 0, 2, 0, 3, 0,
732                                     1, 1, 2, 1, 3, 1, 0, 1,
733                                     2, 2, 3, 2, 0, 2, 1, 2,
734                                     3, 3, 0, 3, 1, 3, 2, 3,
735                                     0, 4, 1, 4, 2, 4, 3, 4,
736                                     1, 5, 2, 5, 3, 5, 0, 5,
737                                     2, 6, 3, 6, 0, 6, 1, 6,
738                                     3, 7, 0, 7, 1, 7, 2, 7};
739 
740   PetscFunctionBeginHot;
741   *rnew = r; *onew = o;
742   if (!so) PetscFunctionReturn(0);
743   switch (sct) {
744     case DM_POLYTOPE_POINT: break;
745     case DM_POLYTOPE_POINT_PRISM_TENSOR:
746     *onew = so < 0 ? -(o+1) : o;
747     break;
748     case DM_POLYTOPE_SEGMENT:
749     switch (tct) {
750       case DM_POLYTOPE_POINT: break;
751       case DM_POLYTOPE_SEGMENT:
752         *rnew = seg_seg[(so+1)*4 + r*2];
753         *onew = DMPolytopeTypeComposeOrientation(tct, o, seg_seg[(so+1)*4 + r*2 + 1]);
754         break;
755       default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
756     }
757     break;
758     case DM_POLYTOPE_TRIANGLE:
759     switch (tct) {
760       case DM_POLYTOPE_SEGMENT:
761         *rnew = tri_seg[(so+3)*6 + r*2];
762         *onew = DMPolytopeTypeComposeOrientation(tct, o, tri_seg[(so+3)*6 + r*2 + 1]);
763         break;
764       case DM_POLYTOPE_TRIANGLE:
765         *rnew = tri_tri[(so+3)*8 + r*2];
766         *onew = DMPolytopeTypeComposeOrientation(tct, o, tri_tri[(so+3)*8 + r*2 + 1]);
767         break;
768       default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
769     }
770     break;
771     case DM_POLYTOPE_QUADRILATERAL:
772     switch (tct) {
773       case DM_POLYTOPE_POINT: break;
774       case DM_POLYTOPE_SEGMENT:
775         *rnew = quad_seg[(so+4)*8 + r*2];
776         *onew = DMPolytopeTypeComposeOrientation(tct, o, quad_seg[(so+4)*8 + r*2 + 1]);
777         break;
778       case DM_POLYTOPE_QUADRILATERAL:
779         *rnew = quad_quad[(so+4)*8 + r*2];
780         *onew = DMPolytopeTypeComposeOrientation(tct, o, quad_quad[(so+4)*8 + r*2 + 1]);
781         break;
782       default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
783     }
784     break;
785     case DM_POLYTOPE_SEG_PRISM_TENSOR:
786     switch (tct) {
787       case DM_POLYTOPE_POINT_PRISM_TENSOR:
788         *rnew = tseg_seg[(so+2)*2 + r*2];
789         *onew = DMPolytopeTypeComposeOrientation(tct, o, tseg_seg[(so+2)*2 + r*2 + 1]);
790         break;
791       case DM_POLYTOPE_SEG_PRISM_TENSOR:
792         *rnew = tseg_tseg[(so+2)*4 + r*2];
793         *onew = DMPolytopeTypeComposeOrientation(tct, o, tseg_tseg[(so+2)*4 + r*2 + 1]);
794         break;
795       default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
796     }
797     break;
798     case DM_POLYTOPE_TETRAHEDRON:
799     switch (tct) {
800       case DM_POLYTOPE_SEGMENT:
801         *rnew = tet_seg[(so+12)*2 + r*2];
802         *onew = DMPolytopeTypeComposeOrientation(tct, o, tet_seg[(so+12)*2 + r*2 + 1]);
803         break;
804       case DM_POLYTOPE_TRIANGLE:
805         *rnew = tet_tri[(so+12)*16 + r*2];
806         *onew = DMPolytopeTypeComposeOrientation(tct, o, tet_tri[(so+12)*16 + r*2 + 1]);
807         break;
808       case DM_POLYTOPE_TETRAHEDRON:
809         *rnew = tet_tet[(so+12)*16 + r*2];
810         *onew = DMPolytopeTypeComposeOrientation(tct, o, tet_tet[(so+12)*16 + r*2 + 1]);
811         break;
812       default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
813     }
814     break;
815     case DM_POLYTOPE_HEXAHEDRON:
816     switch (tct) {
817       case DM_POLYTOPE_POINT: break;
818       case DM_POLYTOPE_SEGMENT:
819         *rnew = hex_seg[(so+24)*12 + r*2];
820         *onew = DMPolytopeTypeComposeOrientation(tct, o, hex_seg[(so+24)*12 + r*2 + 1]);
821         break;
822       case DM_POLYTOPE_QUADRILATERAL:
823         *rnew = hex_quad[(so+24)*24 + r*2];
824         *onew = DMPolytopeTypeComposeOrientation(tct, o, hex_quad[(so+24)*24 + r*2 + 1]);
825         break;
826       case DM_POLYTOPE_HEXAHEDRON:
827         *rnew = hex_hex[(so+24)*16 + r*2];
828         *onew = DMPolytopeTypeComposeOrientation(tct, o, hex_hex[(so+24)*16 + r*2 + 1]);
829         break;
830       default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
831     }
832     break;
833     case DM_POLYTOPE_TRI_PRISM:
834     switch (tct) {
835       case DM_POLYTOPE_SEGMENT:
836         *rnew = trip_seg[(so+6)*6 + r*2];
837         *onew = DMPolytopeTypeComposeOrientation(tct, o, trip_seg[(so+6)*6 + r*2 + 1]);
838         break;
839       case DM_POLYTOPE_TRIANGLE:
840         *rnew = trip_tri[(so+6)*8 + r*2];
841         *onew = DMPolytopeTypeComposeOrientation(tct, o, trip_tri[(so+6)*8 + r*2 + 1]);
842         break;
843       case DM_POLYTOPE_QUADRILATERAL:
844         *rnew = trip_quad[(so+6)*12 + r*2];
845         *onew = DMPolytopeTypeComposeOrientation(tct, o, trip_quad[(so+6)*12 + r*2 + 1]);
846         break;
847       case DM_POLYTOPE_TRI_PRISM:
848         *rnew = trip_trip[(so+6)*16 + r*2];
849         *onew = DMPolytopeTypeComposeOrientation(tct, o, trip_trip[(so+6)*16 + r*2 + 1]);
850         break;
851       default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
852     }
853     break;
854     case DM_POLYTOPE_TRI_PRISM_TENSOR:
855     switch (tct) {
856       case DM_POLYTOPE_SEG_PRISM_TENSOR:
857         *rnew = ttri_tseg[(so+6)*6 + r*2];
858         *onew = DMPolytopeTypeComposeOrientation(tct, o, ttri_tseg[(so+6)*6 + r*2 + 1]);
859         break;
860       case DM_POLYTOPE_TRI_PRISM_TENSOR:
861         *rnew = ttri_ttri[(so+6)*8 + r*2];
862         *onew = DMPolytopeTypeComposeOrientation(tct, o, ttri_ttri[(so+6)*8 + r*2 + 1]);
863         break;
864       default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
865     }
866     break;
867     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
868     switch (tct) {
869       case DM_POLYTOPE_POINT_PRISM_TENSOR:
870         *rnew = tquad_tvert[(so+8)*2 + r*2];
871         *onew = DMPolytopeTypeComposeOrientation(tct, o, tquad_tvert[(so+8)*2 + r*2 + 1]);
872         break;
873       case DM_POLYTOPE_SEG_PRISM_TENSOR:
874         *rnew = tquad_tseg[(so+8)*8 + r*2];
875         *onew = DMPolytopeTypeComposeOrientation(tct, o, tquad_tseg[(so+8)*8 + r*2 + 1]);
876         break;
877       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
878         *rnew = tquad_tquad[(so+8)*8 + r*2];
879         *onew = DMPolytopeTypeComposeOrientation(tct, o, tquad_tquad[(so+8)*8 + r*2 + 1]);
880         break;
881       default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
882     }
883     break;
884     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported cell type %s", DMPolytopeTypes[sct]);
885   }
886   PetscFunctionReturn(0);
887 }
888 
889 PetscErrorCode DMPlexTransformCellRefine_Regular(DMPlexTransform tr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
890 {
891   /* All vertices remain in the refined mesh */
892   static DMPolytopeType vertexT[] = {DM_POLYTOPE_POINT};
893   static PetscInt       vertexS[] = {1};
894   static PetscInt       vertexC[] = {0};
895   static PetscInt       vertexO[] = {0};
896   /* Split all edges with a new vertex, making two new 2 edges
897      0--0--0--1--1
898   */
899   static DMPolytopeType segT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT};
900   static PetscInt       segS[]    = {1, 2};
901   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};
902   static PetscInt       segO[]    = {                         0,                       0,                        0,                          0};
903   /* Do not split tensor edges */
904   static DMPolytopeType tvertT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR};
905   static PetscInt       tvertS[]  = {1};
906   static PetscInt       tvertC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
907   static PetscInt       tvertO[]  = {                         0,                          0};
908   /* Add 3 edges inside every triangle, making 4 new triangles.
909    2
910    |\
911    | \
912    |  \
913    0   1
914    | C  \
915    |     \
916    |      \
917    2---1---1
918    |\  D  / \
919    1 2   0   0
920    |A \ /  B  \
921    0-0-0---1---1
922   */
923   static DMPolytopeType triT[]    = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE};
924   static PetscInt       triS[]    = {3, 4};
925   static PetscInt       triC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
926                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 2, 0,
927                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 0, 0,
928                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1,
929                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0,
930                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0,
931                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2};
932   static PetscInt       triO[]    = {0, 0,
933                                      0, 0,
934                                      0, 0,
935                                      0, -1,  0,
936                                      0,  0, -1,
937                                     -1,  0,  0,
938                                      0,  0,  0};
939   /* Add a vertex in the center of each quadrilateral, and 4 edges inside, making 4 new quads.
940      3----1----2----0----2
941      |         |         |
942      0    D    2    C    1
943      |         |         |
944      3----3----0----1----1
945      |         |         |
946      1    A    0    B    0
947      |         |         |
948      0----0----0----1----1
949   */
950   static DMPolytopeType quadT[]   = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
951   static PetscInt       quadS[]   = {1, 4, 4};
952   static PetscInt       quadC[]   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
953                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
954                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
955                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
956                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1,
957                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
958                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2,
959                                      DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0};
960   static PetscInt       quadO[]   = {0, 0,
961                                      0, 0,
962                                      0, 0,
963                                      0, 0,
964                                      0,  0, -1,  0,
965                                      0,  0,  0, -1,
966                                     -1,  0,  0,  0,
967                                      0, -1,  0,  0};
968   /* Add 1 edge inside every tensor quad, making 2 new tensor quads
969      2----2----1----3----3
970      |         |         |
971      |         |         |
972      |         |         |
973      4    A    6    B    5
974      |         |         |
975      |         |         |
976      |         |         |
977      0----0----0----1----1
978   */
979   static DMPolytopeType tsegT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR};
980   static PetscInt       tsegS[]  = {1, 2};
981   static PetscInt       tsegC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
982                                     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,
983                                     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};
984   static PetscInt       tsegO[]  = {0, 0,
985                                     0, 0, 0, 0,
986                                     0, 0, 0, 0};
987   /* Add 1 edge and 8 triangles inside every cell, making 8 new tets
988      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
989      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]
990      called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are
991        [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3]
992      The first four tets just cut off the corners, using the replica notation for new vertices,
993        [v0,      (e0, 0), (e2, 0), (e3, 0)]
994        [(e0, 0), v1,      (e1, 0), (e4, 0)]
995        [(e2, 0), (e1, 0), v2,      (e5, 0)]
996        [(e3, 0), (e4, 0), (e5, 0), v3     ]
997      The next four tets match a vertex to the newly created faces from cutting off those first tets.
998        [(e2, 0), (e3, 0), (e0, 0), (e5, 0)]
999        [(e4, 0), (e1, 0), (e0, 0), (e5, 0)]
1000        [(e5, 0), (e0, 0), (e2, 0), (e1, 0)]
1001        [(e5, 0), (e0, 0), (e4, 0), (e3, 0)]
1002      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
1003        [(e2, 0), (e0, 0), (e3, 0)]
1004        [(e0, 0), (e1, 0), (e4, 0)]
1005        [(e2, 0), (e5, 0), (e1, 0)]
1006        [(e3, 0), (e4, 0), (e5, 0)]
1007      The next four, from the second group of tets, are
1008        [(e2, 0), (e0, 0), (e5, 0)]
1009        [(e4, 0), (e0, 0), (e5, 0)]
1010        [(e0, 0), (e1, 0), (e5, 0)]
1011        [(e5, 0), (e3, 0), (e0, 0)]
1012      I could write a program to generate these orientations by comparing the faces from GetRawFaces() with my existing table.
1013    */
1014   static DMPolytopeType tetT[]    = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_TETRAHEDRON};
1015   static PetscInt       tetS[]    = {1, 8, 8};
1016   static PetscInt       tetC[]    = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 2, 2, 1, 0,
1017                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 2, 2,
1018                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 1, 1,
1019                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 1, 0, 1,
1020                                      DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 2, 1,
1021                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1022                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 3, 1,
1023                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    0,
1024                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 0,    0,
1025                                      DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 0,    0,
1026                                      DM_POLYTOPE_TRIANGLE, 1, 0, 1, DM_POLYTOPE_TRIANGLE, 1, 1, 2, DM_POLYTOPE_TRIANGLE, 0,    1, DM_POLYTOPE_TRIANGLE, 1, 3, 1,
1027                                      DM_POLYTOPE_TRIANGLE, 1, 0, 2, DM_POLYTOPE_TRIANGLE, 0,    2, DM_POLYTOPE_TRIANGLE, 1, 2, 1, DM_POLYTOPE_TRIANGLE, 1, 3, 0,
1028                                      DM_POLYTOPE_TRIANGLE, 0,    3, DM_POLYTOPE_TRIANGLE, 1, 1, 1, DM_POLYTOPE_TRIANGLE, 1, 2, 2, DM_POLYTOPE_TRIANGLE, 1, 3, 2,
1029                                      DM_POLYTOPE_TRIANGLE, 0,    0, DM_POLYTOPE_TRIANGLE, 1, 2, 3, DM_POLYTOPE_TRIANGLE, 0,    4, DM_POLYTOPE_TRIANGLE, 0,    7,
1030                                      DM_POLYTOPE_TRIANGLE, 0,    1, DM_POLYTOPE_TRIANGLE, 1, 3, 3, DM_POLYTOPE_TRIANGLE, 0,    5, DM_POLYTOPE_TRIANGLE, 0,    6,
1031                                      DM_POLYTOPE_TRIANGLE, 0,    4, DM_POLYTOPE_TRIANGLE, 0,    6, DM_POLYTOPE_TRIANGLE, 0,    2, DM_POLYTOPE_TRIANGLE, 1, 0, 3,
1032                                      DM_POLYTOPE_TRIANGLE, 0,    5, DM_POLYTOPE_TRIANGLE, 0,    7, DM_POLYTOPE_TRIANGLE, 0,    3, DM_POLYTOPE_TRIANGLE, 1, 1, 3};
1033   static PetscInt       tetO[]    = {0, 0,
1034                                      0,  0,  0,
1035                                      0,  0,  0,
1036                                      0,  0,  0,
1037                                      0,  0,  0,
1038                                      0,  0, -1,
1039                                      0,  0, -1,
1040                                      0, -1, -1,
1041                                      0, -1,  0,
1042                                      0,  0,  0,  0,
1043                                      0,  0,  0,  0,
1044                                      0,  0,  0,  0,
1045                                      0,  0,  0,  0,
1046                                     -2,  0,  0, -1,
1047                                     -1,  1,  0,  0,
1048                                     -1, -1, -3,  2,
1049                                     -1,  0, -1,  1};
1050   /* Add a vertex in the center of each cell, add 6 edges and 12 quads inside every cell, making 8 new hexes
1051      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
1052        [v0, v1, v2, v3] f0 bottom
1053        [v4, v5, v6, v7] f1 top
1054        [v0, v3, v5, v4] f2 front
1055        [v2, v1, v7, v6] f3 back
1056        [v3, v2, v6, v5] f4 right
1057        [v0, v4, v7, v1] f5 left
1058      The eight hexes are divided into four on the bottom, and four on the top,
1059        [v0,      (e0, 0),  (f0, 0),  (e3, 0),  (e9, 0), (f2, 0),  (c0, 0),  (f5, 0)]
1060        [(e0, 0), v1,       (e1, 0),  (f0, 0),  (f5, 0), (c0, 0),  (f3, 0),  (e10, 0)]
1061        [(f0, 0), (e1, 0),  v2,       (e2, 0),  (c0, 0), (f4, 0),  (e11, 0), (f3, 0)]
1062        [(e3, 0), (f0, 0),  (e2, 0),  v3,       (f2, 0), (e8, 0),  (f4, 0),  (c0, 0)]
1063        [(e9, 0), (f5, 0),  (c0, 0),  (f2, 0),  v4,      (e4, 0),  (f1, 0),  (e7, 0)]
1064        [(f2, 0), (c0, 0),  (f4, 0),  (e8, 0),  (e4, 0), v5,       (e5, 0),  (f1, 0)]
1065        [(c0, 0), (f3, 0),  (e11, 0), (f4, 0),  (f1, 0), (e5, 0),  v6,       (e6, 0)]
1066        [(f5, 0), (e10, 0), (f3, 0),  (c0, 0),  (e7, 0), (f1, 0),  (e6, 0),  v7]
1067      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,
1068        [(e9, 0), (f2, 0),  (c0, 0),  (f5, 0)]
1069        [(f5, 0), (c0, 0),  (f3, 0),  (e10, 0)]
1070        [(c0, 0), (f4, 0),  (e11, 0), (f3, 0)]
1071        [(f2, 0), (e8, 0),  (f4, 0),  (c0, 0)]
1072      and on the x-z plane,
1073        [(f0, 0), (e0, 0), (f5, 0), (c0, 0)]
1074        [(c0, 0), (f5, 0), (e7, 0), (f1, 0)]
1075        [(f4, 0), (c0, 0), (f1, 0), (e5, 0)]
1076        [(e2, 0), (f0, 0), (c0, 0), (f4, 0)]
1077      and on the y-z plane,
1078        [(e3, 0), (f2, 0), (c0, 0), (f0, 0)]
1079        [(f2, 0), (e4, 0), (f1, 0), (c0, 0)]
1080        [(c0, 0), (f1, 0), (e6, 0), (f3, 0)]
1081        [(f0, 0), (c0, 0), (f3, 0), (e1, 0)]
1082   */
1083   static DMPolytopeType hexT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1084   static PetscInt       hexS[]    = {1, 6, 12, 8};
1085   static PetscInt       hexC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1086                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
1087                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
1088                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
1089                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 0, 0,
1090                                      DM_POLYTOPE_POINT, 1, 5, 0, DM_POLYTOPE_POINT, 0, 0,
1091                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 1, 5, 0,
1092                                      DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 5, 2,
1093                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    3,
1094                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    2,
1095                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 5, 3, DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 0,    0,
1096                                      DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 1, 5, 1, DM_POLYTOPE_SEGMENT, 1, 1, 3, DM_POLYTOPE_SEGMENT, 0,    1,
1097                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 4, 2,
1098                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 0,
1099                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 0, 3,
1100                                      DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2,
1101                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    3,
1102                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 0, 1,
1103                                      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,
1104                                      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,
1105                                      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,
1106                                      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,
1107                                      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,
1108                                      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,
1109                                      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,
1110                                      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};
1111   static PetscInt       hexO[]    = {0, 0,
1112                                      0, 0,
1113                                      0, 0,
1114                                      0, 0,
1115                                      0, 0,
1116                                      0, 0,
1117                                      0,  0, -1, -1,
1118                                      0, -1, -1,  0,
1119                                     -1, -1,  0,  0,
1120                                     -1,  0,  0, -1,
1121                                     -1,  0,  0, -1,
1122                                     -1, -1,  0,  0,
1123                                      0, -1, -1,  0,
1124                                      0,  0, -1, -1,
1125                                      0,  0, -1, -1,
1126                                     -1,  0,  0, -1,
1127                                     -1, -1,  0,  0,
1128                                      0, -1, -1,  0,
1129                                      0, 0,  0, 0, -2, 0,
1130                                      0, 0, -3, 0, -2, 0,
1131                                      0, 0, -3, 0,  0, 0,
1132                                      0, 0,  0, 0,  0, 0,
1133                                     -2, 0,  0, 0, -2, 0,
1134                                     -2, 0,  0, 0,  0, 0,
1135                                     -2, 0, -3, 0,  0, 0,
1136                                     -2, 0, -3, 0, -2, 0};
1137   /* Add 3 quads inside every triangular prism, making 4 new prisms. */
1138   static DMPolytopeType tripT[]   = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_TRI_PRISM};
1139   static PetscInt       tripS[]   = {3, 4, 6, 8};
1140   static PetscInt       tripC[]   = {DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 3, 0,
1141                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 1, 4, 0,
1142                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 1, 2, 0,
1143                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 4, 1,
1144                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    0,
1145                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3,
1146                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2,
1147                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1148                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 4, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 3, 0,
1149                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 4, 0,
1150                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 2,
1151                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 4, 2, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 3, 2,
1152                                      DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 4, 2,
1153                                      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,
1154                                      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,
1155                                      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,
1156                                      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,
1157                                      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,
1158                                      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,
1159                                      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,
1160                                      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};
1161   static PetscInt       tripO[]   = {0, 0,
1162                                      0, 0,
1163                                      0, 0,
1164                                      0, -1, -1,
1165                                     -1,  0, -1,
1166                                     -1, -1,  0,
1167                                      0,  0,  0,
1168                                     -1,  0, -1, -1,
1169                                     -1,  0, -1, -1,
1170                                     -1,  0, -1, -1,
1171                                      0, -1, -1,  0,
1172                                      0, -1, -1,  0,
1173                                      0, -1, -1,  0,
1174                                      0,  0,  0, -3,  0,
1175                                      0,  0,  0,  0, -3,
1176                                      0,  0, -3,  0,  0,
1177                                      2,  0,  0,  0,  0,
1178                                     -2,  0,  0, -3,  0,
1179                                     -2,  0,  0,  0, -3,
1180                                     -2,  0, -3,  0,  0,
1181                                     -2,  0,  0,  0,  0};
1182   /* Add 3 tensor quads inside every tensor triangular prism, making 4 new prisms.
1183       2
1184       |\
1185       | \
1186       |  \
1187       0---1
1188 
1189       2
1190 
1191       0   1
1192 
1193       2
1194       |\
1195       | \
1196       |  \
1197       0---1
1198   */
1199   static DMPolytopeType ttriT[]   = {DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_TRI_PRISM_TENSOR};
1200   static PetscInt       ttriS[]   = {3, 4};
1201   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,
1202                                      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,
1203                                      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,
1204                                      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,
1205                                      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,
1206                                      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,
1207                                      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};
1208   static PetscInt       ttriO[]   = {0, 0, 0, 0,
1209                                      0, 0, 0, 0,
1210                                      0, 0, 0, 0,
1211                                      0, 0,  0, -1,  0,
1212                                      0, 0,  0,  0, -1,
1213                                      0, 0, -1,  0,  0,
1214                                      0, 0,  0,  0,  0};
1215   /* Add 1 edge and 4 tensor quads inside every tensor quad prism, making 4 new prisms. */
1216   static DMPolytopeType tquadT[]   = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
1217   static PetscInt       tquadS[]   = {1, 4, 4};
1218   static PetscInt       tquadC[]   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1219                                       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,
1220                                       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,
1221                                       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,
1222                                       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,
1223                                       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,
1224                                       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,
1225                                       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,
1226                                       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};
1227   static PetscInt       tquadO[]   = {0, 0,
1228                                       0, 0, 0, 0,
1229                                       0, 0, 0, 0,
1230                                       0, 0, 0, 0,
1231                                       0, 0, 0, 0,
1232                                       0, 0,  0,  0, -1,  0,
1233                                       0, 0,  0,  0,  0, -1,
1234                                       0, 0, -1,  0,  0,  0,
1235                                       0, 0,  0, -1,  0,  0};
1236   /* Add 4 edges, 12 triangles, 1 quad, 4 tetrahedra, and 6 pyramids inside every pyramid. */
1237   static DMPolytopeType tpyrT[] = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_TETRAHEDRON, DM_POLYTOPE_PYRAMID};
1238   static PetscInt       tpyrS[] = {4, 12, 1, 4, 6};
1239   static PetscInt       tpyrC[] = {DM_POLYTOPE_POINT, 2, 1, 1, 0, DM_POLYTOPE_POINT, 1, 0, 0,
1240                                    DM_POLYTOPE_POINT, 2, 2, 1, 0, DM_POLYTOPE_POINT, 1, 0, 0,
1241                                    DM_POLYTOPE_POINT, 2, 3, 1, 0, DM_POLYTOPE_POINT, 1, 0, 0,
1242                                    DM_POLYTOPE_POINT, 2, 4, 1, 0, DM_POLYTOPE_POINT, 1, 0, 0,
1243                                    /* These four triangle face out of the bottom pyramid */
1244                                    DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 0, 0,
1245                                    DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1,
1246                                    DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 2,
1247                                    DM_POLYTOPE_SEGMENT, 1, 4, 1, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 3,
1248                                    /* These eight triangles face out of the corner pyramids */
1249                                    DM_POLYTOPE_SEGMENT, 1, 0, 3, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 1, 2,
1250                                    DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 2, 2,
1251                                    DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 3, 2,
1252                                    DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 4, 2,
1253                                    DM_POLYTOPE_SEGMENT, 1, 0, 3, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0,
1254                                    DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    1,
1255                                    DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 0,    2,
1256                                    DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 4, 0, DM_POLYTOPE_SEGMENT, 0,    3,
1257                                    /* This quad faces out of the bottom pyramid */
1258                                    DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 4, 1,
1259                                    /* The bottom face of each tet is on the triangular face */
1260                                    DM_POLYTOPE_TRIANGLE, 1, 1, 3, DM_POLYTOPE_TRIANGLE, 0,  8, DM_POLYTOPE_TRIANGLE, 0, 4, DM_POLYTOPE_TRIANGLE, 0, 0,
1261                                    DM_POLYTOPE_TRIANGLE, 1, 2, 3, DM_POLYTOPE_TRIANGLE, 0,  9, DM_POLYTOPE_TRIANGLE, 0, 5, DM_POLYTOPE_TRIANGLE, 0, 1,
1262                                    DM_POLYTOPE_TRIANGLE, 1, 3, 3, DM_POLYTOPE_TRIANGLE, 0, 10, DM_POLYTOPE_TRIANGLE, 0, 6, DM_POLYTOPE_TRIANGLE, 0, 2,
1263                                    DM_POLYTOPE_TRIANGLE, 1, 4, 3, DM_POLYTOPE_TRIANGLE, 0, 11, DM_POLYTOPE_TRIANGLE, 0, 7, DM_POLYTOPE_TRIANGLE, 0, 3,
1264                                    /* The front face of all pyramids is toward the front */
1265                                    DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_TRIANGLE, 0,    4, DM_POLYTOPE_TRIANGLE, 0,   11, DM_POLYTOPE_TRIANGLE, 1, 4, 1,
1266                                    DM_POLYTOPE_QUADRILATERAL, 1, 0, 3, DM_POLYTOPE_TRIANGLE, 1, 1, 1, DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 0,    5, DM_POLYTOPE_TRIANGLE, 0,    8,
1267                                    DM_POLYTOPE_QUADRILATERAL, 1, 0, 2, DM_POLYTOPE_TRIANGLE, 0,    9, DM_POLYTOPE_TRIANGLE, 1, 2, 1, DM_POLYTOPE_TRIANGLE, 1, 3, 0, DM_POLYTOPE_TRIANGLE, 0,    6,
1268                                    DM_POLYTOPE_QUADRILATERAL, 1, 0, 1, DM_POLYTOPE_TRIANGLE, 0,    7, DM_POLYTOPE_TRIANGLE, 0,   10, DM_POLYTOPE_TRIANGLE, 1, 3, 1, DM_POLYTOPE_TRIANGLE, 1, 4, 0,
1269                                    DM_POLYTOPE_QUADRILATERAL, 0,    0, DM_POLYTOPE_TRIANGLE, 1, 1, 2, DM_POLYTOPE_TRIANGLE, 1, 2, 2, DM_POLYTOPE_TRIANGLE, 1, 3, 2, DM_POLYTOPE_TRIANGLE, 1, 4, 2,
1270                                    DM_POLYTOPE_QUADRILATERAL, 0,    0, DM_POLYTOPE_TRIANGLE, 0,    0, DM_POLYTOPE_TRIANGLE, 0,    3, DM_POLYTOPE_TRIANGLE, 0,    2, DM_POLYTOPE_TRIANGLE, 0,    1,
1271                                    };
1272   static PetscInt       tpyrO[] = {0, 0,
1273                                    0, 0,
1274                                    0, 0,
1275                                    0, 0,
1276                                    0,  0, -1,
1277                                    0,  0, -1,
1278                                    0,  0, -1,
1279                                    0,  0, -1,
1280                                    0, -1,  0,
1281                                    0, -1,  0,
1282                                    0, -1,  0,
1283                                    0, -1,  0,
1284                                   -1,  0,  0,
1285                                   -1,  0,  0,
1286                                   -1,  0,  0,
1287                                   -1,  0,  0,
1288                                   -1, -1, -1, -1,
1289                                    0, -3, -2, -3,
1290                                    0, -3, -2, -3,
1291                                    0, -3, -2, -3,
1292                                    0, -3, -2, -3,
1293                                    0, 0, 0, 0, 0,
1294                                    0, 0, 0, 0, 0,
1295                                    0, 0, 0, 0, 0,
1296                                    0, 0, 0, 0, 0,
1297                                   -2, 0, 0, 0, 0,
1298                                    1, 0, 0, 0, 0};
1299 
1300   PetscFunctionBegin;
1301   if (rt) *rt = 0;
1302   switch (source) {
1303     case DM_POLYTOPE_POINT:              *Nt = 1; *target = vertexT; *size = vertexS; *cone = vertexC; *ornt = vertexO; break;
1304     case DM_POLYTOPE_SEGMENT:            *Nt = 2; *target = segT;    *size = segS;    *cone = segC;    *ornt = segO;    break;
1305     case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tvertT;  *size = tvertS;  *cone = tvertC;  *ornt = tvertO;  break;
1306     case DM_POLYTOPE_TRIANGLE:           *Nt = 2; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1307     case DM_POLYTOPE_QUADRILATERAL:      *Nt = 3; *target = quadT;   *size = quadS;   *cone = quadC;   *ornt = quadO;   break;
1308     case DM_POLYTOPE_SEG_PRISM_TENSOR:   *Nt = 2; *target = tsegT;   *size = tsegS;   *cone = tsegC;   *ornt = tsegO;   break;
1309     case DM_POLYTOPE_TETRAHEDRON:        *Nt = 3; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1310     case DM_POLYTOPE_HEXAHEDRON:         *Nt = 4; *target = hexT;    *size = hexS;    *cone = hexC;    *ornt = hexO;    break;
1311     case DM_POLYTOPE_TRI_PRISM:          *Nt = 4; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
1312     case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 2; *target = ttriT;   *size = ttriS;   *cone = ttriC;   *ornt = ttriO;   break;
1313     case DM_POLYTOPE_QUAD_PRISM_TENSOR:  *Nt = 3; *target = tquadT;  *size = tquadS;  *cone = tquadC;  *ornt = tquadO;  break;
1314     case DM_POLYTOPE_PYRAMID:            *Nt = 5; *target = tpyrT;   *size = tpyrS;   *cone = tpyrC;   *ornt = tpyrO;   break;
1315     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1316   }
1317   PetscFunctionReturn(0);
1318 }
1319 
1320 static PetscErrorCode DMPlexTransformInitialize_Regular(DMPlexTransform tr)
1321 {
1322   PetscFunctionBegin;
1323   tr->ops->view    = DMPlexTransformView_Regular;
1324   tr->ops->setup   = DMPlexTransformSetUp_Regular;
1325   tr->ops->destroy = DMPlexTransformDestroy_Regular;
1326   tr->ops->celltransform = DMPlexTransformCellRefine_Regular;
1327   tr->ops->getsubcellorientation = DMPlexTransformGetSubcellOrientation_Regular;
1328   tr->ops->mapcoordinates = DMPlexTransformMapCoordinatesBarycenter_Internal;
1329   PetscFunctionReturn(0);
1330 }
1331 
1332 PETSC_EXTERN PetscErrorCode DMPlexTransformCreate_Regular(DMPlexTransform tr)
1333 {
1334   DMPlexRefine_Regular *f;
1335 
1336   PetscFunctionBegin;
1337   PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1);
1338   PetscCall(PetscNewLog(tr, &f));
1339   tr->data = f;
1340 
1341   PetscCall(DMPlexTransformInitialize_Regular(tr));
1342   PetscFunctionReturn(0);
1343 }
1344