xref: /petsc/src/dm/impls/plex/plexrefine.c (revision c261946bd862922e0816d499fc28e8dad6dff0aa)
1 #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2 #include <petsc/private/petscfeimpl.h>  /* For PetscFEInterpolate_Static() */
3 #include <petscsf.h>
4 
5 PetscBool SBRcite = PETSC_FALSE;
6 const char SBRCitation[] = "@article{PlazaCarey2000,\n"
7                           "  title   = {Local refinement of simplicial grids based on the skeleton},\n"
8                           "  journal = {Applied Numerical Mathematics},\n"
9                           "  author  = {A. Plaza and Graham F. Carey},\n"
10                           "  volume  = {32},\n"
11                           "  number  = {3},\n"
12                           "  pages   = {195--218},\n"
13                           "  doi     = {10.1016/S0168-9274(99)00022-7},\n"
14                           "  year    = {2000}\n}\n";
15 
16 const char * const DMPlexCellRefinerTypes[] = {"Regular", "ToBox", "ToSimplex", "Alfeld2D", "Alfeld3D", "PowellSabin", "BoundaryLayer", "SBR", "DMPlexCellRefinerTypes", "DM_REFINER_", NULL};
17 
18 /*
19   Note that j and invj are non-square:
20          v0 + j x_face = x_cell
21     invj (x_cell - v0) = x_face
22 */
23 static PetscErrorCode DMPlexCellRefinerGetAffineFaceTransforms_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nf, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[], PetscReal *detJ[])
24 {
25   /*
26    2
27    |\
28    | \
29    |  \
30    |   \
31    |    \
32    |     \
33    |      \
34    2       1
35    |        \
36    |         \
37    |          \
38    0---0-------1
39    v0[Nf][dc]:       3 x 2
40    J[Nf][df][dc]:    3 x 1 x 2
41    invJ[Nf][dc][df]: 3 x 2 x 1
42    detJ[Nf]:         3
43    */
44   static PetscReal tri_v0[]   = {0.0, -1.0,  0.0, 0.0,  -1.0,  0.0};
45   static PetscReal tri_J[]    = {1.0, 0.0,  -1.0, 1.0,   0.0, -1.0};
46   static PetscReal tri_invJ[] = {1.0, 0.0,  -0.5, 0.5,   0.0, -1.0};
47   static PetscReal tri_detJ[] = {1.0,  1.414213562373095,  1.0};
48   /*
49    3---------2---------2
50    |                   |
51    |                   |
52    |                   |
53    3                   1
54    |                   |
55    |                   |
56    |                   |
57    0---------0---------1
58 
59    v0[Nf][dc]:       4 x 2
60    J[Nf][df][dc]:    4 x 1 x 2
61    invJ[Nf][dc][df]: 4 x 2 x 1
62    detJ[Nf]:         4
63    */
64   static PetscReal quad_v0[]   = {0.0, -1.0,  1.0, 0.0,   0.0, 1.0  -1.0,  0.0};
65   static PetscReal quad_J[]    = {1.0, 0.0,   0.0, 1.0,  -1.0, 0.0,  0.0, -1.0};
66   static PetscReal quad_invJ[] = {1.0, 0.0,   0.0, 1.0,  -1.0, 0.0,  0.0, -1.0};
67   static PetscReal quad_detJ[] = {1.0,  1.0,  1.0,  1.0};
68 
69   PetscFunctionBegin;
70   switch (ct) {
71   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;
72   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;
73   default:
74     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
75   }
76   PetscFunctionReturn(0);
77 }
78 
79 /* Gets the affine map from the original cell to each subcell */
80 static PetscErrorCode DMPlexCellRefinerGetAffineTransforms_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nc, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[])
81 {
82   /*
83    2
84    |\
85    | \
86    |  \
87    |   \
88    | C  \
89    |     \
90    |      \
91    2---1---1
92    |\  D  / \
93    | 2   0   \
94    |A \ /  B  \
95    0---0-------1
96    */
97   static PetscReal tri_v0[]   = {-1.0, -1.0,  0.0, -1.0,  -1.0, 0.0,  0.0, -1.0};
98   static PetscReal tri_J[]    = {0.5, 0.0,
99                                  0.0, 0.5,
100 
101                                  0.5, 0.0,
102                                  0.0, 0.5,
103 
104                                  0.5, 0.0,
105                                  0.0, 0.5,
106 
107                                  0.0, -0.5,
108                                  0.5,  0.5};
109   static PetscReal tri_invJ[] = {2.0, 0.0,
110                                  0.0, 2.0,
111 
112                                  2.0, 0.0,
113                                  0.0, 2.0,
114 
115                                  2.0, 0.0,
116                                  0.0, 2.0,
117 
118                                  2.0,  2.0,
119                                 -2.0,  0.0};
120     /*
121      3---------2---------2
122      |         |         |
123      |    D    2    C    |
124      |         |         |
125      3----3----0----1----1
126      |         |         |
127      |    A    0    B    |
128      |         |         |
129      0---------0---------1
130      */
131   static PetscReal quad_v0[]   = {-1.0, -1.0,  0.0, -1.0,  0.0, 0.0,  -1.0, 0.0};
132   static PetscReal quad_J[]    = {0.5, 0.0,
133                                   0.0, 0.5,
134 
135                                   0.5, 0.0,
136                                   0.0, 0.5,
137 
138                                   0.5, 0.0,
139                                   0.0, 0.5,
140 
141                                   0.5, 0.0,
142                                   0.0, 0.5};
143   static PetscReal quad_invJ[] = {2.0, 0.0,
144                                   0.0, 2.0,
145 
146                                   2.0, 0.0,
147                                   0.0, 2.0,
148 
149                                   2.0, 0.0,
150                                   0.0, 2.0,
151 
152                                   2.0, 0.0,
153                                   0.0, 2.0};
154     /*
155      Bottom (viewed from top)    Top
156      1---------2---------2       7---------2---------6
157      |         |         |       |         |         |
158      |    B    2    C    |       |    H    2    G    |
159      |         |         |       |         |         |
160      3----3----0----1----1       3----3----0----1----1
161      |         |         |       |         |         |
162      |    A    0    D    |       |    E    0    F    |
163      |         |         |       |         |         |
164      0---------0---------3       4---------0---------5
165      */
166   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,
167                                  -1.0, -1.0,  0.0,   0.0, -1.0,  0.0,  0.0, 0.0,  0.0,  -1.0,  0.0,  0.0};
168   static PetscReal hex_J[]    = {0.5, 0.0, 0.0,
169                                  0.0, 0.5, 0.0,
170                                  0.0, 0.0, 0.5,
171 
172                                  0.5, 0.0, 0.0,
173                                  0.0, 0.5, 0.0,
174                                  0.0, 0.0, 0.5,
175 
176                                  0.5, 0.0, 0.0,
177                                  0.0, 0.5, 0.0,
178                                  0.0, 0.0, 0.5,
179 
180                                  0.5, 0.0, 0.0,
181                                  0.0, 0.5, 0.0,
182                                  0.0, 0.0, 0.5,
183 
184                                  0.5, 0.0, 0.0,
185                                  0.0, 0.5, 0.0,
186                                  0.0, 0.0, 0.5,
187 
188                                  0.5, 0.0, 0.0,
189                                  0.0, 0.5, 0.0,
190                                  0.0, 0.0, 0.5,
191 
192                                  0.5, 0.0, 0.0,
193                                  0.0, 0.5, 0.0,
194                                  0.0, 0.0, 0.5,
195 
196                                  0.5, 0.0, 0.0,
197                                  0.0, 0.5, 0.0,
198                                  0.0, 0.0, 0.5};
199   static PetscReal hex_invJ[] = {2.0, 0.0, 0.0,
200                                  0.0, 2.0, 0.0,
201                                  0.0, 0.0, 2.0,
202 
203                                  2.0, 0.0, 0.0,
204                                  0.0, 2.0, 0.0,
205                                  0.0, 0.0, 2.0,
206 
207                                  2.0, 0.0, 0.0,
208                                  0.0, 2.0, 0.0,
209                                  0.0, 0.0, 2.0,
210 
211                                  2.0, 0.0, 0.0,
212                                  0.0, 2.0, 0.0,
213                                  0.0, 0.0, 2.0,
214 
215                                  2.0, 0.0, 0.0,
216                                  0.0, 2.0, 0.0,
217                                  0.0, 0.0, 2.0,
218 
219                                  2.0, 0.0, 0.0,
220                                  0.0, 2.0, 0.0,
221                                  0.0, 0.0, 2.0,
222 
223                                  2.0, 0.0, 0.0,
224                                  0.0, 2.0, 0.0,
225                                  0.0, 0.0, 2.0,
226 
227                                  2.0, 0.0, 0.0,
228                                  0.0, 2.0, 0.0,
229                                  0.0, 0.0, 2.0};
230 
231   PetscFunctionBegin;
232   switch (ct) {
233   case DM_POLYTOPE_TRIANGLE:      if (Nc) *Nc = 4; if (v0) *v0 = tri_v0;  if (J) *J = tri_J;  if (invJ) *invJ = tri_invJ;  break;
234   case DM_POLYTOPE_QUADRILATERAL: if (Nc) *Nc = 4; if (v0) *v0 = quad_v0; if (J) *J = quad_J; if (invJ) *invJ = quad_invJ; break;
235   case DM_POLYTOPE_HEXAHEDRON:    if (Nc) *Nc = 8; if (v0) *v0 = hex_v0;  if (J) *J = hex_J;  if (invJ) *invJ = hex_invJ;  break;
236   default:
237     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
238   }
239   PetscFunctionReturn(0);
240 }
241 
242 /* Should this be here or in the DualSpace somehow? */
243 PetscErrorCode CellRefinerInCellTest_Internal(DMPolytopeType ct, const PetscReal point[], PetscBool *inside)
244 {
245   PetscReal sum = 0.0;
246   PetscInt  d;
247 
248   PetscFunctionBegin;
249   *inside = PETSC_TRUE;
250   switch (ct) {
251   case DM_POLYTOPE_TRIANGLE:
252   case DM_POLYTOPE_TETRAHEDRON:
253     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) {
254       if (point[d] < -1.0) {*inside = PETSC_FALSE; break;}
255       sum += point[d];
256     }
257     if (sum > PETSC_SMALL) {*inside = PETSC_FALSE; break;}
258     break;
259   case DM_POLYTOPE_QUADRILATERAL:
260   case DM_POLYTOPE_HEXAHEDRON:
261     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d)
262       if (PetscAbsReal(point[d]) > 1.+PETSC_SMALL) {*inside = PETSC_FALSE; break;}
263     break;
264   default:
265     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
266   }
267   PetscFunctionReturn(0);
268 }
269 
270 /* Regular Refinment of Hybrid Meshes
271 
272    We would like to express regular refinement as a small set of rules that can be applied on every point of the Plex
273    to automatically generate a refined Plex. In fact, we would like these rules to be general enough to encompass other
274    transformations, such as changing from one type of cell to another, as simplex to hex.
275 
276    To start, we can create a function that takes an original cell type and returns the number of new cells replacing it
277    and the types of the new cells.
278 
279    We need the group multiplication table for group actions from the dihedral group for each cell type.
280 
281    We need an operator which takes in a cell, and produces a new set of cells with new faces and correct orientations. I think
282    we can just write this operator for faces with identity, and then compose the face orientation actions to get the actual
283    (face, orient) pairs for each subcell.
284 */
285 
286 /*
287   Input Parameters:
288 + ct - The type of the input cell
289 . co - The orientation of this cell in its parent
290 - cp - The requested cone point of this cell assuming orientation 0
291 
292   Output Parameters:
293 . cpnew - The new cone point, taking into account the orientation co
294 */
295 PETSC_STATIC_INLINE PetscErrorCode DMPolytopeMapCell(DMPolytopeType ct, PetscInt co, PetscInt cp, PetscInt *cpnew)
296 {
297   const PetscInt csize = DMPolytopeTypeGetConeSize(ct);
298 
299   PetscFunctionBeginHot;
300   if (ct == DM_POLYTOPE_POINT) {*cpnew = cp;}
301   else                         {*cpnew = (co < 0 ? -(co+1)-cp+csize : co+cp)%csize;}
302   PetscFunctionReturn(0);
303 }
304 
305 static PetscErrorCode DMPlexCellRefinerGetCellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
306 {
307   static PetscReal seg_v[]  = {-1.0,  0.0,  1.0};
308   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};
309   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};
310   static PetscReal tet_v[]  = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
311                                -1.0,  0.0, -1.0,   0.0,  0.0, -1.0,  -1.0,  1.0, -1.0,
312                                -1.0, -1.0,  0.0,   0.0, -1.0,  0.0,  -1.0,  0.0,  0.0,  -1.0, -1.0,  1.0};
313   static PetscReal hex_v[]  = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
314                                -1.0,  0.0, -1.0,   0.0,  0.0, -1.0,   1.0,  0.0, -1.0,
315                                -1.0,  1.0, -1.0,   0.0,  1.0, -1.0,   1.0,  1.0, -1.0,
316                                -1.0, -1.0,  0.0,   0.0, -1.0,  0.0,   1.0, -1.0,  0.0,
317                                -1.0,  0.0,  0.0,   0.0,  0.0,  0.0,   1.0,  0.0,  0.0,
318                                -1.0,  1.0,  0.0,   0.0,  1.0,  0.0,   1.0,  1.0,  0.0,
319                                -1.0, -1.0,  1.0,   0.0, -1.0,  1.0,   1.0, -1.0,  1.0,
320                                -1.0,  0.0,  1.0,   0.0,  0.0,  1.0,   1.0,  0.0,  1.0,
321                                -1.0,  1.0,  1.0,   0.0,  1.0,  1.0,   1.0,  1.0,  1.0};
322 
323   PetscFunctionBegin;
324   switch (ct) {
325     case DM_POLYTOPE_SEGMENT:       *Nv =  3; *subcellV = seg_v;  break;
326     case DM_POLYTOPE_TRIANGLE:      *Nv =  6; *subcellV = tri_v;  break;
327     case DM_POLYTOPE_QUADRILATERAL: *Nv =  9; *subcellV = quad_v; break;
328     case DM_POLYTOPE_TETRAHEDRON:   *Nv = 10; *subcellV = tet_v;  break;
329     case DM_POLYTOPE_HEXAHEDRON:    *Nv = 27; *subcellV = hex_v;  break;
330     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
331   }
332   PetscFunctionReturn(0);
333 }
334 
335 static PetscErrorCode DMPlexCellRefinerGetCellVertices_ToBox(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
336 {
337   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,  -1.0/3.0, -1.0/3.0};
338   static PetscReal tet_v[] = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
339                               -1.0,  0.0, -1.0,  -1.0/3.0, -1.0/3.0, -1.0,   0.0,  0.0, -1.0,  -1.0,  1.0, -1.0,
340                               -1.0, -1.0,  0.0,  -1.0/3.0, -1.0, -1.0/3.0,   0.0, -1.0,  0.0,
341                               -1.0, -1.0/3.0, -1.0/3.0,  -1.0/3.0, -1.0/3.0, -1.0/3.0,  -1.0,  0.0,  0.0,
342                               -1.0, -1.0,  1.0,  -0.5, -0.5, -0.5};
343   PetscErrorCode   ierr;
344 
345   PetscFunctionBegin;
346   switch (ct) {
347     case DM_POLYTOPE_SEGMENT:
348     case DM_POLYTOPE_QUADRILATERAL:
349     case DM_POLYTOPE_HEXAHEDRON:
350       ierr = DMPlexCellRefinerGetCellVertices_Regular(cr, ct, Nv, subcellV);CHKERRQ(ierr);break;
351     case DM_POLYTOPE_TRIANGLE:    *Nv =  7; *subcellV = tri_v; break;
352     case DM_POLYTOPE_TETRAHEDRON: *Nv = 15; *subcellV = tet_v;  break;
353     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
354   }
355   PetscFunctionReturn(0);
356 }
357 
358 /*
359   DMPlexCellRefinerGetCellVertices - Get the set of refined vertices lying in the closure of a reference cell of given type
360 
361   Input Parameters:
362 + cr - The DMPlexCellRefiner object
363 - ct - The cell type
364 
365   Output Parameters:
366 + Nv       - The number of refined vertices in the closure of the reference cell of given type
367 - subcellV - The coordinates of these vertices in the reference cell
368 
369   Level: developer
370 
371 .seealso: DMPlexCellRefinerGetSubcellVertices()
372 */
373 static PetscErrorCode DMPlexCellRefinerGetCellVertices(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
374 {
375   PetscErrorCode ierr;
376 
377   PetscFunctionBegin;
378   if (!cr->ops->getcellvertices) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]);
379   ierr = (*cr->ops->getcellvertices)(cr, ct, Nv, subcellV);CHKERRQ(ierr);
380   PetscFunctionReturn(0);
381 }
382 
383 static PetscErrorCode DMPlexCellRefinerGetSubcellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
384 {
385   static PetscInt seg_v[]  = {0, 1, 1, 2};
386   static PetscInt tri_v[]  = {0, 3, 5,  3, 1, 4,  5, 4, 2,  3, 4, 5};
387   static PetscInt quad_v[] = {0, 4, 8, 7,  4, 1, 5, 8,  8, 5, 2, 6,  7, 8, 6, 3};
388   static PetscInt tet_v[]  = {0, 3, 1, 6,  3, 2, 4, 8,  1, 4, 5, 7,  6, 8, 7, 9,
389                               1, 6, 3, 7,  8, 4, 3, 7,  7, 3, 1, 4,  7, 3, 8, 6};
390   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,
391                               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};
392 
393   PetscFunctionBegin;
394   if (ct != rct) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]);
395   switch (ct) {
396     case DM_POLYTOPE_SEGMENT:       *Nv = 2; *subcellV = &seg_v[r*(*Nv)];  break;
397     case DM_POLYTOPE_TRIANGLE:      *Nv = 3; *subcellV = &tri_v[r*(*Nv)];  break;
398     case DM_POLYTOPE_QUADRILATERAL: *Nv = 4; *subcellV = &quad_v[r*(*Nv)]; break;
399     case DM_POLYTOPE_TETRAHEDRON:   *Nv = 4; *subcellV = &tet_v[r*(*Nv)];  break;
400     case DM_POLYTOPE_HEXAHEDRON:    *Nv = 8; *subcellV = &hex_v[r*(*Nv)];  break;
401     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
402   }
403   PetscFunctionReturn(0);
404 }
405 
406 static PetscErrorCode DMPlexCellRefinerGetSubcellVertices_ToBox(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
407 {
408   static PetscInt tri_v[]  = {0, 3, 6, 5,  3, 1, 4, 6,  5, 6, 4, 2};
409   static PetscInt tet_v[]  = {0,  3,  4,  1,  7,  8, 14, 10,   6, 12, 11,  5,  3,  4, 14, 10,   2,  5, 11,  9,  1,  8, 14,  4,  13, 12 , 10,  7,  9,  8, 14, 11};
410   PetscErrorCode  ierr;
411 
412   PetscFunctionBegin;
413   switch (ct) {
414     case DM_POLYTOPE_SEGMENT:
415     case DM_POLYTOPE_QUADRILATERAL:
416     case DM_POLYTOPE_HEXAHEDRON:
417       ierr = DMPlexCellRefinerGetSubcellVertices_Regular(cr, ct, rct, r, Nv, subcellV);CHKERRQ(ierr);break;
418     case DM_POLYTOPE_TRIANGLE:
419       if (rct != DM_POLYTOPE_QUADRILATERAL) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]);
420       *Nv = 4; *subcellV = &tri_v[r*(*Nv)]; break;
421     case DM_POLYTOPE_TETRAHEDRON:
422       if (rct != DM_POLYTOPE_HEXAHEDRON) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]);
423       *Nv = 8; *subcellV = &tet_v[r*(*Nv)]; break;
424     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
425   }
426   PetscFunctionReturn(0);
427 }
428 
429 /*
430   DMPlexCellRefinerGetSubcellVertices - Get the set of refined vertices defining a subcell in the reference cell of given type
431 
432   Input Parameters:
433 + cr  - The DMPlexCellRefiner object
434 . ct  - The cell type
435 . rct - The type of subcell
436 - r   - The subcell index
437 
438   Output Parameters:
439 + Nv       - The number of refined vertices in the subcell
440 - subcellV - The indices of these vertices in the set of vertices returned by DMPlexCellRefinerGetCellVertices()
441 
442   Level: developer
443 
444 .seealso: DMPlexCellRefinerGetCellVertices()
445 */
446 static PetscErrorCode DMPlexCellRefinerGetSubcellVertices(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
447 {
448   PetscErrorCode ierr;
449 
450   PetscFunctionBegin;
451   if (!cr->ops->getsubcellvertices) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]);
452   ierr = (*cr->ops->getsubcellvertices)(cr, ct, rct, r, Nv, subcellV);CHKERRQ(ierr);
453   PetscFunctionReturn(0);
454 }
455 
456 /*
457   Input Parameters:
458 + cr   - The DMPlexCellRefiner
459 . pct  - The cell type of the parent, from whom the new cell is being produced
460 . ct   - The type being produced
461 . r    - The replica number requested for the produced cell type
462 . Nv   - Number of vertices in the closure of the parent cell
463 . dE   - Spatial dimension
464 - in   - array of size Nv*dE, holding coordinates of the vertices in the closure of the parent cell
465 
466   Output Parameters:
467 . out - The coordinates of the new vertices
468 */
469 static PetscErrorCode DMPlexCellRefinerMapCoordinates(DMPlexCellRefiner cr, DMPolytopeType pct, DMPolytopeType ct, PetscInt r, PetscInt Nv, PetscInt dE, const PetscScalar in[], PetscScalar out[])
470 {
471   PetscErrorCode ierr;
472 
473   PetscFunctionBeginHot;
474   if (!cr->ops->mapcoords) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]);
475   ierr = (*cr->ops->mapcoords)(cr, pct, ct, r, Nv, dE, in, out);CHKERRQ(ierr);
476   PetscFunctionReturn(0);
477 }
478 
479 /* Computes new vertex as the barycenter */
480 static PetscErrorCode DMPlexCellRefinerMapCoordinates_Barycenter(DMPlexCellRefiner cr, DMPolytopeType pct, DMPolytopeType ct, PetscInt r, PetscInt Nv, PetscInt dE, const PetscScalar in[], PetscScalar out[])
481 {
482   PetscInt v,d;
483 
484   PetscFunctionBeginHot;
485   if (ct != DM_POLYTOPE_POINT) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for refined point type %s",DMPolytopeTypes[ct]);
486   for (d = 0; d < dE; ++d) out[d] = 0.0;
487   for (v = 0; v < Nv; ++v) for (d = 0; d < dE; ++d) out[d] += in[v*dE+d];
488   for (d = 0; d < dE; ++d) out[d] /= Nv;
489   PetscFunctionReturn(0);
490 }
491 
492 /*
493   Input Parameters:
494 + cr  - The DMPlexCellRefiner
495 . pct - The cell type of the parent, from whom the new cell is being produced
496 . pp  - The parent cell
497 . po  - The orientation of the parent cell in its enclosing parent
498 . ct  - The type being produced
499 . r   - The replica number requested for the produced cell type
500 - o   - The relative orientation of the replica
501 
502   Output Parameters:
503 + rnew - The replica number, given the orientation of the parent
504 - onew - The replica orientation, given the orientation of the parent
505 */
506 static PetscErrorCode DMPlexCellRefinerMapSubcells(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
507 {
508   PetscErrorCode ierr;
509 
510   PetscFunctionBeginHot;
511   if (!cr->ops->mapsubcells) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]);
512   ierr = (*cr->ops->mapsubcells)(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
513   PetscFunctionReturn(0);
514 }
515 
516 /*
517   This is the group multiplication table for the dihedral group of the cell.
518 */
519 static PetscErrorCode ComposeOrientation_Private(PetscInt n, PetscInt o1, PetscInt o2, PetscInt *o)
520 {
521   PetscFunctionBeginHot;
522   if (!n)                      {*o = 0;}
523   else if (o1 >= 0 && o2 >= 0) {*o = ( o1 + o2) % n;}
524   else if (o1 <  0 && o2 <  0) {*o = (-o1 - o2) % n;}
525   else if (o1 < 0)             {*o = -((-(o1+1) + o2) % n + 1);}
526   else if (o2 < 0)             {*o = -((-(o2+1) + o1) % n + 1);}
527   PetscFunctionReturn(0);
528 }
529 
530 static PetscErrorCode DMPlexCellRefinerMapSubcells_None(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
531 {
532   PetscErrorCode ierr;
533 
534   PetscFunctionBeginHot;
535   *rnew = r;
536   ierr  = ComposeOrientation_Private(DMPolytopeTypeGetConeSize(ct), po, o, onew);CHKERRQ(ierr);
537   PetscFunctionReturn(0);
538 }
539 
540 static PetscErrorCode DMPlexCellRefinerMapSubcells_Regular(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
541 {
542   /* We shift any input orientation in order to make it non-negative
543        The orientation array o[po][o] gives the orientation the new replica rnew has to have in order to reproduce the face sequence from (r, o)
544        The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po
545        Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po
546   */
547   PetscInt tri_seg_o[] = {-2, 0,
548                           -2, 0,
549                           -2, 0,
550                           0, -2,
551                           0, -2,
552                           0, -2};
553   PetscInt tri_seg_r[] = {1, 0, 2,
554                           0, 2, 1,
555                           2, 1, 0,
556                           0, 1, 2,
557                           1, 2, 0,
558                           2, 0, 1};
559   PetscInt tri_tri_o[] = {0,  1,  2, -3, -2, -1,
560                           2,  0,  1, -2, -1, -3,
561                           1,  2,  0, -1, -3, -2,
562                          -3, -2, -1,  0,  1,  2,
563                          -1, -3, -2,  1,  2,  0,
564                          -2, -1, -3,  2,  0,  1};
565   /* orientation if the replica is the center triangle */
566   PetscInt tri_tri_o_c[] = {2,  0,  1, -2, -1, -3,
567                             1,  2,  0, -1, -3, -2,
568                             0,  1,  2, -3, -2, -1,
569                            -3, -2, -1,  0,  1,  2,
570                            -1, -3, -2,  1,  2,  0,
571                            -2, -1, -3,  2,  0,  1};
572   PetscInt tri_tri_r[] = {0, 2, 1, 3,
573                           2, 1, 0, 3,
574                           1, 0, 2, 3,
575                           0, 1, 2, 3,
576                           1, 2, 0, 3,
577                           2, 0, 1, 3};
578   PetscInt quad_seg_r[] = {3, 2, 1, 0,
579                            2, 1, 0, 3,
580                            1, 0, 3, 2,
581                            0, 3, 2, 1,
582                            0, 1, 2, 3,
583                            1, 2, 3, 0,
584                            2, 3, 0, 1,
585                            3, 0, 1, 2};
586   PetscInt quad_quad_o[] = { 0,  1,  2,  3, -4, -3, -2, -1,
587                              4,  0,  1,  2, -3, -2, -1, -4,
588                              3,  4,  0,  1, -2, -1, -4, -3,
589                              2,  3,  4,  0, -1, -4, -3, -2,
590                             -4, -3, -2, -1,  0,  1,  2,  3,
591                             -1, -4, -3, -2,  1,  2,  3,  0,
592                             -2, -1, -4, -3,  2,  3,  0,  1,
593                             -3, -2, -1, -4,  3,  0,  1,  2};
594   PetscInt quad_quad_r[] = {0, 3, 2, 1,
595                             3, 2, 1, 0,
596                             2, 1, 0, 3,
597                             1, 0, 3, 2,
598                             0, 1, 2, 3,
599                             1, 2, 3, 0,
600                             2, 3, 0, 1,
601                             3, 0, 1, 2};
602   PetscInt tquad_tquad_o[] = { 0,  1, -2, -1,
603                                1,  0, -1, -2,
604                               -2, -1,  0,  1,
605                               -1, -2,  1,  0};
606   PetscInt tquad_tquad_r[] = {1, 0,
607                               1, 0,
608                               0, 1,
609                               0, 1};
610 
611   PetscFunctionBeginHot;
612   /* The default is no transformation */
613   *rnew = r;
614   *onew = o;
615   switch (pct) {
616     case DM_POLYTOPE_SEGMENT:
617       if (ct == DM_POLYTOPE_SEGMENT) {
618         if      (po == 0 || po == -1) {*rnew = r;       *onew = o;}
619         else if (po == 1 || po == -2) {*rnew = (r+1)%2; *onew = (o == 0 || o == -1) ? -2 : 0;}
620         else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid orientation %D for segment", po);
621       }
622       break;
623     case DM_POLYTOPE_TRIANGLE:
624       switch (ct) {
625         case DM_POLYTOPE_SEGMENT:
626           if (o == -1) o = 0;
627           if (o == -2) o = 1;
628           *onew = tri_seg_o[(po+3)*2+o];
629           *rnew = tri_seg_r[(po+3)*3+r];
630           break;
631         case DM_POLYTOPE_TRIANGLE:
632           *onew = r == 3 && po < 0 ? tri_tri_o_c[((po+3)%3)*6+o+3] : tri_tri_o[(po+3)*6+o+3];
633           *rnew = tri_tri_r[(po+3)*4+r];
634           break;
635         default: break;
636       }
637       break;
638     case DM_POLYTOPE_QUADRILATERAL:
639       switch (ct) {
640         case DM_POLYTOPE_SEGMENT:
641           *onew = o;
642           *rnew = quad_seg_r[(po+4)*4+r];
643           break;
644         case DM_POLYTOPE_QUADRILATERAL:
645           *onew = quad_quad_o[(po+4)*8+o+4];
646           *rnew = quad_quad_r[(po+4)*4+r];
647           break;
648         default: break;
649       }
650       break;
651     case DM_POLYTOPE_SEG_PRISM_TENSOR:
652       switch (ct) {
653         /* DM_POLYTOPE_POINT_PRISM_TENSOR does not change */
654         case DM_POLYTOPE_SEG_PRISM_TENSOR:
655           *onew = tquad_tquad_o[(po+2)*4+o+2];
656           *rnew = tquad_tquad_r[(po+2)*2+r];
657           break;
658         default: break;
659       }
660       break;
661     default: break;
662   }
663   PetscFunctionReturn(0);
664 }
665 
666 static PetscErrorCode DMPlexCellRefinerMapSubcells_ToBox(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
667 {
668   PetscErrorCode ierr;
669   /* We shift any input orientation in order to make it non-negative
670        The orientation array o[po][o] gives the orientation the new replica rnew has to have in order to reproduce the face sequence from (r, o)
671        The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po
672        Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po
673   */
674   PetscInt tri_seg_o[] = {0, -2,
675                           0, -2,
676                           0, -2,
677                           0, -2,
678                           0, -2,
679                           0, -2};
680   PetscInt tri_seg_r[] = {2, 1, 0,
681                           1, 0, 2,
682                           0, 2, 1,
683                           0, 1, 2,
684                           1, 2, 0,
685                           2, 0, 1};
686   PetscInt tri_tri_o[] = {0,  1,  2,  3, -4, -3, -2, -1,
687                           3,  0,  1,  2, -3, -2, -1, -4,
688                           1,  2,  3,  0, -1, -4, -3, -2,
689                          -4, -3, -2, -1,  0,  1,  2,  3,
690                          -1, -4, -3, -2,  1,  2,  3,  0,
691                          -3, -2, -1, -4,  3,  0,  1,  2};
692   PetscInt tri_tri_r[] = {0, 2, 1,
693                           2, 1, 0,
694                           1, 0, 2,
695                           0, 1, 2,
696                           1, 2, 0,
697                           2, 0, 1};
698   PetscInt tquad_tquad_o[] = { 0,  1, -2, -1,
699                                1,  0, -1, -2,
700                               -2, -1,  0,  1,
701                               -1, -2,  1,  0};
702   PetscInt tquad_tquad_r[] = {1, 0,
703                               1, 0,
704                               0, 1,
705                               0, 1};
706   PetscInt tquad_quad_o[] = {-2, -1, -4, -3,  2,  3,  0,  1,
707                               1,  2,  3,  0, -1, -4, -3, -2,
708                              -4, -3, -2, -1,  0,  1,  2,  3,
709                               1,  0,  3,  2, -3, -4, -1, -2};
710 
711   PetscFunctionBeginHot;
712   *rnew = r;
713   *onew = o;
714   switch (pct) {
715     case DM_POLYTOPE_TRIANGLE:
716       switch (ct) {
717         case DM_POLYTOPE_SEGMENT:
718           if (o == -1) o = 0;
719           if (o == -2) o = 1;
720           *onew = tri_seg_o[(po+3)*2+o];
721           *rnew = tri_seg_r[(po+3)*3+r];
722           break;
723         case DM_POLYTOPE_QUADRILATERAL:
724           *onew = tri_tri_o[(po+3)*8+o+4];
725           /* TODO See sheet, for fixing po == 1 and 2 */
726           if (po ==  2 && r == 2 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+3)%4)+4];
727           if (po ==  2 && r == 2 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+5)%4)];
728           if (po ==  1 && r == 1 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+1)%4)+4];
729           if (po ==  1 && r == 1 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+7)%4)];
730           if (po == -1 && r == 2 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+3)%4)+4];
731           if (po == -1 && r == 2 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+5)%4)];
732           if (po == -2 && r == 1 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+1)%4)+4];
733           if (po == -2 && r == 1 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+7)%4)];
734           *rnew = tri_tri_r[(po+3)*3+r];
735           break;
736         default: break;
737       }
738       break;
739     case DM_POLYTOPE_SEG_PRISM_TENSOR:
740       switch (ct) {
741         /* DM_POLYTOPE_POINT_PRISM_TENSOR does not change */
742         case DM_POLYTOPE_SEG_PRISM_TENSOR:
743           *onew = tquad_tquad_o[(po+2)*4+o+2];
744           *rnew = tquad_tquad_r[(po+2)*2+r];
745           break;
746         case DM_POLYTOPE_QUADRILATERAL:
747           *onew = tquad_quad_o[(po+2)*8+o+4];
748           *rnew = tquad_tquad_r[(po+2)*2+r];
749           break;
750         default: break;
751       }
752       break;
753     default:
754       ierr = DMPlexCellRefinerMapSubcells_Regular(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
755   }
756   PetscFunctionReturn(0);
757 }
758 
759 static PetscErrorCode DMPlexCellRefinerMapSubcells_ToSimplex(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
760 {
761   return DMPlexCellRefinerMapSubcells_Regular(cr, pct, pp, po, ct, r, o, rnew, onew);
762 }
763 
764 /*@
765   DMPlexCellRefinerRefine - Return a description of the refinement for a given cell type
766 
767   Input Parameters:
768 + source - The cell type for a source point
769 - p      - The source point, or PETSC_DETERMINE if the refine is homogeneous
770 
771   Output Parameters:
772 + rt     - The refine type for this cell
773 . Nt     - The number of cell types generated by refinement
774 . target - The cell types generated
775 . size   - The number of subcells of each type, ordered by dimension
776 . cone   - A list of the faces for each subcell of the same type as source
777 - ornt   - A list of the face orientations for each subcell of the same type as source
778 
779   Note: The cone array gives the cone of each subcell listed by the first three outputs. For each cone point, we
780   need the cell type, point identifier, and orientation within the subcell. The orientation is with respect to the canonical
781   division (described in these outputs) of the cell in the original mesh. The point identifier is given by
782 $   the number of cones to be taken, or 0 for the current cell
783 $   the cell cone point number at each level from which it is subdivided
784 $   the replica number r of the subdivision.
785   The orientation is with respect to the canonical cone orientation. For example, the prescription for edge division is
786 $   Nt     = 2
787 $   target = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT}
788 $   size   = {1, 2}
789 $   cone   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,  DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0}
790 $   ornt   = {                         0,                       0,                        0,                          0}
791 
792   Level: developer
793 
794 .seealso: DMPlexCellRefinerCreate(), DMPlexRefineUniform()
795 @*/
796 PetscErrorCode DMPlexCellRefinerRefine(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
797 {
798   PetscErrorCode ierr;
799 
800   PetscFunctionBeginHot;
801   if (!cr->ops->refine) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]);
802   ierr = (*cr->ops->refine)(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
803   PetscFunctionReturn(0);
804 }
805 
806 static PetscErrorCode DMPlexCellRefinerRefine_None(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
807 {
808   static DMPolytopeType vertexT[] = {DM_POLYTOPE_POINT};
809   static PetscInt       vertexS[] = {1};
810   static PetscInt       vertexC[] = {0};
811   static PetscInt       vertexO[] = {0};
812   static DMPolytopeType edgeT[]   = {DM_POLYTOPE_SEGMENT};
813   static PetscInt       edgeS[]   = {1};
814   static PetscInt       edgeC[]   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
815   static PetscInt       edgeO[]   = {0, 0};
816   static DMPolytopeType tedgeT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR};
817   static PetscInt       tedgeS[]  = {1};
818   static PetscInt       tedgeC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
819   static PetscInt       tedgeO[]  = {0, 0};
820   static DMPolytopeType triT[]    = {DM_POLYTOPE_TRIANGLE};
821   static PetscInt       triS[]    = {1};
822   static PetscInt       triC[]    = {DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0};
823   static PetscInt       triO[]    = {0, 0, 0};
824   static DMPolytopeType quadT[]   = {DM_POLYTOPE_QUADRILATERAL};
825   static PetscInt       quadS[]   = {1};
826   static PetscInt       quadC[]   = {DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 3, 0};
827   static PetscInt       quadO[]   = {0, 0, 0, 0};
828   static DMPolytopeType tquadT[]  = {DM_POLYTOPE_SEG_PRISM_TENSOR};
829   static PetscInt       tquadS[]  = {1};
830   static PetscInt       tquadC[]  = {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};
831   static PetscInt       tquadO[]  = {0, 0, 0, 0};
832   static DMPolytopeType tetT[]    = {DM_POLYTOPE_TETRAHEDRON};
833   static PetscInt       tetS[]    = {1};
834   static PetscInt       tetC[]    = {DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 1, 3, 0};
835   static PetscInt       tetO[]    = {0, 0, 0, 0};
836   static DMPolytopeType hexT[]    = {DM_POLYTOPE_HEXAHEDRON};
837   static PetscInt       hexS[]    = {1};
838   static PetscInt       hexC[]    = {DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0,
839                                      DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0, DM_POLYTOPE_QUADRILATERAL, 1, 5, 0};
840   static PetscInt       hexO[]    = {0, 0, 0, 0, 0, 0};
841   static DMPolytopeType tripT[]   = {DM_POLYTOPE_TRI_PRISM};
842   static PetscInt       tripS[]   = {1};
843   static PetscInt       tripC[]   = {DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0,
844                                      DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0};
845   static PetscInt       tripO[]   = {0, 0, 0, 0, 0};
846   static DMPolytopeType ttripT[]  = {DM_POLYTOPE_TRI_PRISM_TENSOR};
847   static PetscInt       ttripS[]  = {1};
848   static PetscInt       ttripC[]  = {DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0,
849                                      DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0};
850   static PetscInt       ttripO[]  = {0, 0, 0, 0, 0};
851   static DMPolytopeType tquadpT[] = {DM_POLYTOPE_QUAD_PRISM_TENSOR};
852   static PetscInt       tquadpS[] = {1};
853   static PetscInt       tquadpC[] = {DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0,
854                                      DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 5, 0};
855   static PetscInt       tquadpO[] = {0, 0, 0, 0, 0, 0};
856   static DMPolytopeType pyrT[]    = {DM_POLYTOPE_PYRAMID};
857   static PetscInt       pyrS[]    = {1};
858   static PetscInt       pyrC[]    = {DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0,
859                                      DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 1, 3, 0, DM_POLYTOPE_TRIANGLE, 1, 4, 0};
860   static PetscInt       pyrO[]    = {0, 0, 0, 0, 0};
861 
862   PetscFunctionBegin;
863   if (rt) *rt = 0;
864   switch (source) {
865     case DM_POLYTOPE_POINT:              *Nt = 1; *target = vertexT; *size = vertexS; *cone = vertexC; *ornt = vertexO; break;
866     case DM_POLYTOPE_SEGMENT:            *Nt = 1; *target = edgeT;   *size = edgeS;   *cone = edgeC;   *ornt = edgeO;   break;
867     case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT;  *size = tedgeS;  *cone = tedgeC;  *ornt = tedgeO;  break;
868     case DM_POLYTOPE_TRIANGLE:           *Nt = 1; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
869     case DM_POLYTOPE_QUADRILATERAL:      *Nt = 1; *target = quadT;   *size = quadS;   *cone = quadC;   *ornt = quadO;   break;
870     case DM_POLYTOPE_SEG_PRISM_TENSOR:   *Nt = 1; *target = tquadT;  *size = tquadS;  *cone = tquadC;  *ornt = tquadO;  break;
871     case DM_POLYTOPE_TETRAHEDRON:        *Nt = 1; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
872     case DM_POLYTOPE_HEXAHEDRON:         *Nt = 1; *target = hexT;    *size = hexS;    *cone = hexC;    *ornt = hexO;    break;
873     case DM_POLYTOPE_TRI_PRISM:          *Nt = 1; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
874     case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 1; *target = ttripT;  *size = ttripS;  *cone = ttripC;  *ornt = ttripO;  break;
875     case DM_POLYTOPE_QUAD_PRISM_TENSOR:  *Nt = 1; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break;
876     case DM_POLYTOPE_PYRAMID:            *Nt = 1; *target = pyrT;    *size = pyrS;    *cone = pyrC;    *ornt = pyrO;    break;
877     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
878   }
879   PetscFunctionReturn(0);
880 }
881 
882 static PetscErrorCode DMPlexCellRefinerRefine_Regular(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
883 {
884   /* All vertices remain in the refined mesh */
885   static DMPolytopeType vertexT[] = {DM_POLYTOPE_POINT};
886   static PetscInt       vertexS[] = {1};
887   static PetscInt       vertexC[] = {0};
888   static PetscInt       vertexO[] = {0};
889   /* Split all edges with a new vertex, making two new 2 edges
890      0--0--0--1--1
891   */
892   static DMPolytopeType edgeT[]   = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT};
893   static PetscInt       edgeS[]   = {1, 2};
894   static PetscInt       edgeC[]   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,  DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
895   static PetscInt       edgeO[]   = {                         0,                       0,                        0,                          0};
896   /* Do not split tensor edges */
897   static DMPolytopeType tedgeT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR};
898   static PetscInt       tedgeS[]  = {1};
899   static PetscInt       tedgeC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
900   static PetscInt       tedgeO[]  = {                         0,                          0};
901   /* Add 3 edges inside every triangle, making 4 new triangles.
902    2
903    |\
904    | \
905    |  \
906    0   1
907    | C  \
908    |     \
909    |      \
910    2---1---1
911    |\  D  / \
912    1 2   0   0
913    |A \ /  B  \
914    0-0-0---1---1
915   */
916   static DMPolytopeType triT[]    = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE};
917   static PetscInt       triS[]    = {3, 4};
918   static PetscInt       triC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
919                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 2, 0,
920                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 0, 0,
921                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1,
922                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0,
923                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0,
924                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2};
925   static PetscInt       triO[]    = {0, 0,
926                                      0, 0,
927                                      0, 0,
928                                      0, -2,  0,
929                                      0,  0, -2,
930                                     -2,  0,  0,
931                                      0,  0,  0};
932   /* Add a vertex in the center of each quadrilateral, and 4 edges inside, making 4 new quads.
933      3----1----2----0----2
934      |         |         |
935      0    D    2    C    1
936      |         |         |
937      3----3----0----1----1
938      |         |         |
939      1    A    0    B    0
940      |         |         |
941      0----0----0----1----1
942   */
943   static DMPolytopeType quadT[]   = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
944   static PetscInt       quadS[]   = {1, 4, 4};
945   static PetscInt       quadC[]   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
946                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
947                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
948                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
949                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1,
950                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
951                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2,
952                                      DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0};
953   static PetscInt       quadO[]   = {0, 0,
954                                      0, 0,
955                                      0, 0,
956                                      0, 0,
957                                      0,  0, -2,  0,
958                                      0,  0,  0, -2,
959                                     -2,  0,  0,  0,
960                                      0, -2,  0,  0};
961   /* Add 1 edge inside every tensor quad, making 2 new tensor quads
962      2----2----1----3----3
963      |         |         |
964      |         |         |
965      |         |         |
966      4    A    6    B    5
967      |         |         |
968      |         |         |
969      |         |         |
970      0----0----0----1----1
971   */
972   static DMPolytopeType tquadT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR};
973   static PetscInt       tquadS[]  = {1, 2};
974   static PetscInt       tquadC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
975                                      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,
976                                      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};
977   static PetscInt       tquadO[]  = {0, 0,
978                                      0, 0, 0, 0,
979                                      0, 0, 0, 0};
980   /* Add 1 edge and 8 triangles inside every cell, making 8 new tets
981      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
982      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]
983      called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are
984        [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3]
985      The first four tets just cut off the corners, using the replica notation for new vertices,
986        [v0,      (e0, 0), (e2, 0), (e3, 0)]
987        [(e0, 0), v1,      (e1, 0), (e4, 0)]
988        [(e2, 0), (e1, 0), v2,      (e5, 0)]
989        [(e3, 0), (e4, 0), (e5, 0), v3     ]
990      The next four tets match a vertex to the newly created faces from cutting off those first tets.
991        [(e2, 0), (e3, 0), (e0, 0), (e5, 0)]
992        [(e4, 0), (e1, 0), (e0, 0), (e5, 0)]
993        [(e5, 0), (e0, 0), (e2, 0), (e1, 0)]
994        [(e5, 0), (e0, 0), (e4, 0), (e3, 0)]
995      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
996        [(e2, 0), (e0, 0), (e3, 0)]
997        [(e0, 0), (e1, 0), (e4, 0)]
998        [(e2, 0), (e5, 0), (e1, 0)]
999        [(e3, 0), (e4, 0), (e5, 0)]
1000      The next four, from the second group of tets, are
1001        [(e2, 0), (e0, 0), (e5, 0)]
1002        [(e4, 0), (e0, 0), (e5, 0)]
1003        [(e0, 0), (e1, 0), (e5, 0)]
1004        [(e5, 0), (e3, 0), (e0, 0)]
1005      I could write a program to generate these orientations by comparing the faces from GetRawFaces() with my existing table.
1006    */
1007   static DMPolytopeType tetT[]    = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_TETRAHEDRON};
1008   static PetscInt       tetS[]    = {1, 8, 8};
1009   static PetscInt       tetC[]    = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 2, 2, 1, 0,
1010                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 2, 2,
1011                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 1, 1,
1012                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 1, 0, 1,
1013                                      DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 2, 1,
1014                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1015                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 3, 1,
1016                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    0,
1017                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 0,    0,
1018                                      DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 0,    0,
1019                                      DM_POLYTOPE_TRIANGLE, 1, 0, 1, DM_POLYTOPE_TRIANGLE, 1, 1, 2, DM_POLYTOPE_TRIANGLE, 0,    1, DM_POLYTOPE_TRIANGLE, 1, 3, 1,
1020                                      DM_POLYTOPE_TRIANGLE, 1, 0, 2, DM_POLYTOPE_TRIANGLE, 0,    2, DM_POLYTOPE_TRIANGLE, 1, 2, 1, DM_POLYTOPE_TRIANGLE, 1, 3, 0,
1021                                      DM_POLYTOPE_TRIANGLE, 0,    3, DM_POLYTOPE_TRIANGLE, 1, 1, 1, DM_POLYTOPE_TRIANGLE, 1, 2, 2, DM_POLYTOPE_TRIANGLE, 1, 3, 2,
1022                                      DM_POLYTOPE_TRIANGLE, 0,    0, DM_POLYTOPE_TRIANGLE, 1, 2, 3, DM_POLYTOPE_TRIANGLE, 0,    4, DM_POLYTOPE_TRIANGLE, 0,    7,
1023                                      DM_POLYTOPE_TRIANGLE, 0,    1, DM_POLYTOPE_TRIANGLE, 1, 3, 3, DM_POLYTOPE_TRIANGLE, 0,    5, DM_POLYTOPE_TRIANGLE, 0,    6,
1024                                      DM_POLYTOPE_TRIANGLE, 0,    4, DM_POLYTOPE_TRIANGLE, 0,    6, DM_POLYTOPE_TRIANGLE, 0,    2, DM_POLYTOPE_TRIANGLE, 1, 0, 3,
1025                                      DM_POLYTOPE_TRIANGLE, 0,    5, DM_POLYTOPE_TRIANGLE, 0,    7, DM_POLYTOPE_TRIANGLE, 0,    3, DM_POLYTOPE_TRIANGLE, 1, 1, 3};
1026   static PetscInt       tetO[]    = {0, 0,
1027                                      0,  0,  0,
1028                                      0,  0,  0,
1029                                      0,  0,  0,
1030                                      0,  0,  0,
1031                                      0,  0, -2,
1032                                      0,  0, -2,
1033                                      0, -2, -2,
1034                                      0, -2,  0,
1035                                      0,  0,  0,  0,
1036                                      0,  0,  0,  0,
1037                                      0,  0,  0,  0,
1038                                      0,  0,  0,  0,
1039                                     -3,  0,  0, -2,
1040                                     -2,  1,  0,  0,
1041                                     -2, -2, -1,  2,
1042                                     -2,  0, -2,  1};
1043   /* Add a vertex in the center of each cell, add 6 edges and 12 quads inside every cell, making 8 new hexes
1044      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
1045        [v0, v1, v2, v3] f0 bottom
1046        [v4, v5, v6, v7] f1 top
1047        [v0, v3, v5, v4] f2 front
1048        [v2, v1, v7, v6] f3 back
1049        [v3, v2, v6, v5] f4 right
1050        [v0, v4, v7, v1] f5 left
1051      The eight hexes are divided into four on the bottom, and four on the top,
1052        [v0,      (e0, 0),  (f0, 0),  (e3, 0),  (e9, 0), (f2, 0),  (c0, 0),  (f5, 0)]
1053        [(e0, 0), v1,       (e1, 0),  (f0, 0),  (f5, 0), (c0, 0),  (f3, 0),  (e10, 0)]
1054        [(f0, 0), (e1, 0),  v2,       (e2, 0),  (c0, 0), (f4, 0),  (e11, 0), (f3, 0)]
1055        [(e3, 0), (f0, 0),  (e2, 0),  v3,       (f2, 0), (e8, 0),  (f4, 0),  (c0, 0)]
1056        [(e9, 0), (f5, 0),  (c0, 0),  (f2, 0),  v4,      (e4, 0),  (f1, 0),  (e7, 0)]
1057        [(f2, 0), (c0, 0),  (f4, 0),  (e8, 0),  (e4, 0), v5,       (e5, 0),  (f1, 0)]
1058        [(c0, 0), (f3, 0),  (e11, 0), (f4, 0),  (f1, 0), (e5, 0),  v6,       (e6, 0)]
1059        [(f5, 0), (e10, 0), (f3, 0),  (c0, 0),  (e7, 0), (f1, 0),  (e6, 0),  v7]
1060      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,
1061        [(e9, 0), (f2, 0),  (c0, 0),  (f5, 0)]
1062        [(f5, 0), (c0, 0),  (f3, 0),  (e10, 0)]
1063        [(c0, 0), (f4, 0),  (e11, 0), (f3, 0)]
1064        [(f2, 0), (e8, 0),  (f4, 0),  (c0, 0)]
1065      and on the x-z plane,
1066        [(f0, 0), (e0, 0), (f5, 0), (c0, 0)]
1067        [(c0, 0), (f5, 0), (e7, 0), (f1, 0)]
1068        [(f4, 0), (c0, 0), (f1, 0), (e5, 0)]
1069        [(e2, 0), (f0, 0), (c0, 0), (f4, 0)]
1070      and on the y-z plane,
1071        [(e3, 0), (f2, 0), (c0, 0), (f0, 0)]
1072        [(f2, 0), (e4, 0), (f1, 0), (c0, 0)]
1073        [(c0, 0), (f1, 0), (e6, 0), (f3, 0)]
1074        [(f0, 0), (c0, 0), (f3, 0), (e1, 0)]
1075   */
1076   static DMPolytopeType hexT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1077   static PetscInt       hexS[]    = {1, 6, 12, 8};
1078   static PetscInt       hexC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1079                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
1080                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
1081                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
1082                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 0, 0,
1083                                      DM_POLYTOPE_POINT, 1, 5, 0, DM_POLYTOPE_POINT, 0, 0,
1084                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 1, 5, 0,
1085                                      DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 5, 2,
1086                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    3,
1087                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    2,
1088                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 5, 3, DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 0,    0,
1089                                      DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 1, 5, 1, DM_POLYTOPE_SEGMENT, 1, 1, 3, DM_POLYTOPE_SEGMENT, 0,    1,
1090                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 4, 2,
1091                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 0,
1092                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 0, 3,
1093                                      DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2,
1094                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    3,
1095                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 0, 1,
1096                                      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,
1097                                      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,
1098                                      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,
1099                                      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,
1100                                      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,
1101                                      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,
1102                                      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,
1103                                      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};
1104   static PetscInt       hexO[]    = {0, 0,
1105                                      0, 0,
1106                                      0, 0,
1107                                      0, 0,
1108                                      0, 0,
1109                                      0, 0,
1110                                      0,  0, -2, -2,
1111                                      0, -2, -2,  0,
1112                                     -2, -2,  0,  0,
1113                                     -2,  0,  0, -2,
1114                                     -2,  0,  0, -2,
1115                                     -2, -2,  0,  0,
1116                                      0, -2, -2,  0,
1117                                      0,  0, -2, -2,
1118                                      0,  0, -2, -2,
1119                                     -2,  0,  0, -2,
1120                                     -2, -2,  0,  0,
1121                                      0, -2, -2,  0,
1122                                      0, 0,  0, 0, -4, 0,
1123                                      0, 0, -1, 0, -4, 0,
1124                                      0, 0, -1, 0,  0, 0,
1125                                      0, 0,  0, 0,  0, 0,
1126                                     -4, 0,  0, 0, -4, 0,
1127                                     -4, 0,  0, 0,  0, 0,
1128                                     -4, 0, -1, 0,  0, 0,
1129                                     -4, 0, -1, 0, -4, 0};
1130   /* Add 3 quads inside every triangular prism, making 4 new prisms. */
1131   static DMPolytopeType tripT[]   = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_TRI_PRISM};
1132   static PetscInt       tripS[]   = {3, 4, 6, 8};
1133   static PetscInt       tripC[]   = {DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 3, 0,
1134                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 1, 4, 0,
1135                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 1, 2, 0,
1136                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 4, 1,
1137                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    0,
1138                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3,
1139                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2,
1140                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1141                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 4, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 3, 0,
1142                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 4, 0,
1143                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 2,
1144                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 4, 2, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 3, 2,
1145                                      DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 4, 2,
1146                                      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,
1147                                      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,
1148                                      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,
1149                                      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,
1150                                      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,
1151                                      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,
1152                                      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,
1153                                      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};
1154   static PetscInt       tripO[]   = {0, 0,
1155                                      0, 0,
1156                                      0, 0,
1157                                      0, -2, -2,
1158                                     -2,  0, -2,
1159                                     -2, -2,  0,
1160                                      0,  0,  0,
1161                                     -2,  0, -2, -2,
1162                                     -2,  0, -2, -2,
1163                                     -2,  0, -2, -2,
1164                                      0, -2, -2,  0,
1165                                      0, -2, -2,  0,
1166                                      0, -2, -2,  0,
1167                                      0,  0,  0, -1,  0,
1168                                      0,  0,  0,  0, -1,
1169                                      0,  0, -1,  0,  0,
1170                                      2,  0,  0,  0,  0,
1171                                     -3,  0,  0, -1,  0,
1172                                     -3,  0,  0,  0, -1,
1173                                     -3,  0, -1,  0,  0,
1174                                     -3,  0,  0,  0,  0};
1175   /* Add 3 tensor quads inside every tensor triangular prism, making 4 new prisms.
1176       2
1177       |\
1178       | \
1179       |  \
1180       0---1
1181 
1182       2
1183 
1184       0   1
1185 
1186       2
1187       |\
1188       | \
1189       |  \
1190       0---1
1191   */
1192   static DMPolytopeType ttripT[]  = {DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_TRI_PRISM_TENSOR};
1193   static PetscInt       ttripS[]  = {3, 4};
1194   static PetscInt       ttripC[]  = {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,
1195                                      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,
1196                                      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,
1197                                      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,
1198                                      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,
1199                                      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,
1200                                      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};
1201   static PetscInt       ttripO[]  = {0, 0, 0, 0,
1202                                      0, 0, 0, 0,
1203                                      0, 0, 0, 0,
1204                                      0, 0,  0, -1,  0,
1205                                      0, 0,  0,  0, -1,
1206                                      0, 0, -1,  0,  0,
1207                                      0, 0,  0,  0,  0};
1208   /* Add 1 edge and 4 tensor quads inside every tensor quad prism, making 4 new prisms. */
1209   static DMPolytopeType tquadpT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
1210   static PetscInt       tquadpS[]  = {1, 4, 4};
1211   static PetscInt       tquadpC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1212                                       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,
1213                                       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,
1214                                       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,
1215                                       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,
1216                                       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,
1217                                       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,
1218                                       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,
1219                                       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};
1220   static PetscInt       tquadpO[]  = {0, 0,
1221                                       0, 0, 0, 0,
1222                                       0, 0, 0, 0,
1223                                       0, 0, 0, 0,
1224                                       0, 0, 0, 0,
1225                                       0, 0,  0,  0, -1,  0,
1226                                       0, 0,  0,  0,  0, -1,
1227                                       0, 0, -1,  0,  0,  0,
1228                                       0, 0,  0, -1,  0,  0};
1229   PetscErrorCode ierr;
1230 
1231   PetscFunctionBegin;
1232   if (rt) *rt = 0;
1233   switch (source) {
1234     case DM_POLYTOPE_POINT:              *Nt = 1; *target = vertexT; *size = vertexS; *cone = vertexC; *ornt = vertexO; break;
1235     case DM_POLYTOPE_SEGMENT:            *Nt = 2; *target = edgeT;   *size = edgeS;   *cone = edgeC;   *ornt = edgeO;   break;
1236     case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT;  *size = tedgeS;  *cone = tedgeC;  *ornt = tedgeO;  break;
1237     case DM_POLYTOPE_TRIANGLE:           *Nt = 2; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1238     case DM_POLYTOPE_QUADRILATERAL:      *Nt = 3; *target = quadT;   *size = quadS;   *cone = quadC;   *ornt = quadO;   break;
1239     case DM_POLYTOPE_SEG_PRISM_TENSOR:   *Nt = 2; *target = tquadT;  *size = tquadS;  *cone = tquadC;  *ornt = tquadO;  break;
1240     case DM_POLYTOPE_TETRAHEDRON:        *Nt = 3; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1241     case DM_POLYTOPE_HEXAHEDRON:         *Nt = 4; *target = hexT;    *size = hexS;    *cone = hexC;    *ornt = hexO;    break;
1242     case DM_POLYTOPE_TRI_PRISM:          *Nt = 4; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
1243     case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 2; *target = ttripT;  *size = ttripS;  *cone = ttripC;  *ornt = ttripO;  break;
1244     case DM_POLYTOPE_QUAD_PRISM_TENSOR:  *Nt = 3; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break;
1245     /* TODO Fix pyramids: For now, we just ignore them */
1246     case DM_POLYTOPE_PYRAMID:
1247       ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1248       break;
1249     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1250   }
1251   PetscFunctionReturn(0);
1252 }
1253 
1254 static PetscErrorCode DMPlexCellRefinerRefine_ToBox(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
1255 {
1256   PetscErrorCode ierr;
1257   /* Change tensor edges to segments */
1258   static DMPolytopeType tedgeT[]  = {DM_POLYTOPE_SEGMENT};
1259   static PetscInt       tedgeS[]  = {1};
1260   static PetscInt       tedgeC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
1261   static PetscInt       tedgeO[]  = {                         0,                          0};
1262   /* Add 1 vertex, 3 edges inside every triangle, making 3 new quadrilaterals.
1263    2
1264    |\
1265    | \
1266    |  \
1267    |   \
1268    0    1
1269    |     \
1270    |      \
1271    2       1
1272    |\     / \
1273    | 2   1   \
1274    |  \ /     \
1275    1   |       0
1276    |   0        \
1277    |   |         \
1278    |   |          \
1279    0-0-0-----1-----1
1280   */
1281   static DMPolytopeType triT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
1282   static PetscInt       triS[]    = {1, 3, 3};
1283   static PetscInt       triC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0,    0,
1284                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0,    0,
1285                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0,    0,
1286                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1,
1287                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
1288                                      DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0};
1289   static PetscInt       triO[]    = {0, 0,
1290                                      0, 0,
1291                                      0, 0,
1292                                      0,  0, -2,  0,
1293                                      0,  0,  0, -2,
1294                                      0, -2,  0,  0};
1295   /* Add 1 edge inside every tensor quad, making 2 new quadrilaterals
1296      2----2----1----3----3
1297      |         |         |
1298      |         |         |
1299      |         |         |
1300      4    A    6    B    5
1301      |         |         |
1302      |         |         |
1303      |         |         |
1304      0----0----0----1----1
1305   */
1306   static DMPolytopeType tquadT[]  = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
1307   static PetscInt       tquadS[]  = {1, 2};
1308   static PetscInt       tquadC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1309                                      /* TODO  Fix these */
1310                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1311                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0,    0};
1312   static PetscInt       tquadO[]  = {0, 0,
1313                                      0, 0, -2, -2,
1314                                      0, 0, -2, -2};
1315   /* Add 6 triangles inside every cell, making 4 new hexs
1316      TODO: Need different SubcellMap(). Need to make a struct with the function pointers in it
1317      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
1318      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]
1319      called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are
1320        [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3]
1321      We make a new hex in each corner
1322        [v0, (e0, 0), (f0, 0), (e2, 0), (e3, 0), (f2, 0), (c0, 0), (f1, 0)]
1323        [v1, (e4, 0), (f3, 0), (e1, 0), (e0, 0), (f0, 0), (c0, 0), (f1, 0)]
1324        [v2, (e1, 0), (f3, 0), (e5, 0), (e2, 0), (f2, 0), (c0, 0), (f0, 0)]
1325        [v3, (e4, 0), (f1, 0), (e3, 0), (e5, 0), (f2, 0), (c0, 0), (f3, 0)]
1326      We create a new face for each edge
1327        [(e3, 0), (f2, 0), (c0, 0), (f1, 0)]
1328        [(f0, 0), (e0, 0), (f1, 0), (c0, 0)]
1329        [(e2, 0), (f0, 0), (c0, 0), (f2, 0)]
1330        [(f3, 0), (e4, 0), (f1, 0), (c0, 0)]
1331        [(e1, 0), (f3, 0), (c0, 0), (f0, 0)]
1332        [(e5, 0), (f3, 0), (c0, 0), (f2, 0)]
1333      I could write a program to generate these from the first hex by acting with the symmetry group to take one subcell into another.
1334    */
1335   static DMPolytopeType tetT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1336   static PetscInt       tetS[]    = {1, 4, 6, 4};
1337   static PetscInt       tetC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1338                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
1339                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
1340                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
1341                                      DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 0,
1342                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
1343                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1344                                      DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    3,
1345                                      DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 0, 1,
1346                                      DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1,
1347                                      DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 0,    0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 0,    1, DM_POLYTOPE_QUADRILATERAL, 0,    2, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0,
1348                                      DM_POLYTOPE_QUADRILATERAL, 1, 3, 1, DM_POLYTOPE_QUADRILATERAL, 0,    1, DM_POLYTOPE_QUADRILATERAL, 1, 0, 1, DM_POLYTOPE_QUADRILATERAL, 0,    3, DM_POLYTOPE_QUADRILATERAL, 0,    4, DM_POLYTOPE_QUADRILATERAL, 1, 1, 2,
1349                                      DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 0,    2, DM_POLYTOPE_QUADRILATERAL, 1, 2, 1, DM_POLYTOPE_QUADRILATERAL, 0,    4, DM_POLYTOPE_QUADRILATERAL, 0,    5, DM_POLYTOPE_QUADRILATERAL, 1, 0, 2,
1350                                      DM_POLYTOPE_QUADRILATERAL, 1, 1, 1, DM_POLYTOPE_QUADRILATERAL, 0,    5, DM_POLYTOPE_QUADRILATERAL, 1, 2, 2, DM_POLYTOPE_QUADRILATERAL, 0,    3, DM_POLYTOPE_QUADRILATERAL, 0,    0, DM_POLYTOPE_QUADRILATERAL, 1, 3, 2};
1351   static PetscInt       tetO[]    = {0, 0,
1352                                      0, 0,
1353                                      0, 0,
1354                                      0, 0,
1355                                      0,  0, -2, -2,
1356                                     -2,  0,  0, -2,
1357                                      0,  0, -2, -2,
1358                                     -2,  0,  0, -2,
1359                                      0,  0, -2, -2,
1360                                      0,  0, -2, -2,
1361                                      0,  0,  0,  0,  0,  0,
1362                                      1, -1,  1,  0,  0,  3,
1363                                      0, -4,  1, -1,  0,  3,
1364                                      1, -4,  3, -2, -4,  3};
1365   /* Add 3 quads inside every triangular prism, making 4 new prisms. */
1366   static DMPolytopeType tripT[]   = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1367   static PetscInt       tripS[]   = {1, 5, 9, 6};
1368   static PetscInt       tripC[]   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1369                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
1370                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
1371                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
1372                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 0, 0,
1373                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 1,
1374                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    2,
1375                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3,
1376                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1377                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 0,
1378                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 0,
1379                                      DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 2,
1380                                      DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 3, 2,
1381                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 4, 2,
1382                                      DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 0,    0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 0,    5, DM_POLYTOPE_QUADRILATERAL, 0,    3, DM_POLYTOPE_QUADRILATERAL, 1, 4, 1,
1383                                      DM_POLYTOPE_QUADRILATERAL, 1, 0, 2, DM_POLYTOPE_QUADRILATERAL, 0,    1, DM_POLYTOPE_QUADRILATERAL, 1, 2, 1, DM_POLYTOPE_QUADRILATERAL, 0,    4, DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 0,    3,
1384                                      DM_POLYTOPE_QUADRILATERAL, 1, 0, 1, DM_POLYTOPE_QUADRILATERAL, 0,    2, DM_POLYTOPE_QUADRILATERAL, 0,    5, DM_POLYTOPE_QUADRILATERAL, 1, 3, 1, DM_POLYTOPE_QUADRILATERAL, 0,    4, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0,
1385                                      DM_POLYTOPE_QUADRILATERAL, 0,    0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 3, DM_POLYTOPE_QUADRILATERAL, 0,    8, DM_POLYTOPE_QUADRILATERAL, 0,    6, DM_POLYTOPE_QUADRILATERAL, 1, 4, 2,
1386                                      DM_POLYTOPE_QUADRILATERAL, 0,    1, DM_POLYTOPE_QUADRILATERAL, 1, 1, 1, DM_POLYTOPE_QUADRILATERAL, 1, 2, 2, DM_POLYTOPE_QUADRILATERAL, 0,    7, DM_POLYTOPE_QUADRILATERAL, 1, 3, 3, DM_POLYTOPE_QUADRILATERAL, 0,    6,
1387                                      DM_POLYTOPE_QUADRILATERAL, 0,    2, DM_POLYTOPE_QUADRILATERAL, 1, 1, 2, DM_POLYTOPE_QUADRILATERAL, 0,    8, DM_POLYTOPE_QUADRILATERAL, 1, 3, 2, DM_POLYTOPE_QUADRILATERAL, 0,    7, DM_POLYTOPE_QUADRILATERAL, 1, 4, 3};
1388   static PetscInt       tripO[]   = {0, 0,
1389                                      0, 0,
1390                                      0, 0,
1391                                      0, 0,
1392                                      0, 0,
1393                                      0,  0, -2, -2,
1394                                     -2,  0,  0, -2,
1395                                      0, -2, -2,  0,
1396                                      0,  0, -2, -2,
1397                                      0,  0, -2, -2,
1398                                      0,  0, -2, -2,
1399                                      0, -2, -2,  0,
1400                                      0, -2, -2,  0,
1401                                      0, -2, -2,  0,
1402                                      0,  0,  0, -1,  0,  1,
1403                                      0,  0,  0,  0,  0, -4,
1404                                      0,  0,  0,  0, -1,  1,
1405                                     -4,  0,  0, -1,  0,  1,
1406                                     -4,  0,  0,  0,  0, -4,
1407                                     -4,  0,  0,  0, -1,  1};
1408   /* Add 3 tensor quads inside every tensor triangular prism, making 4 new tensor triangular prisms.
1409       2
1410       |\
1411       | \
1412       |  \
1413       0---1
1414 
1415       2
1416 
1417       0   1
1418 
1419       2
1420       |\
1421       | \
1422       |  \
1423       0---1
1424   */
1425   static DMPolytopeType ttripT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
1426   static PetscInt       ttripS[]  = {1, 3, 3};
1427   static PetscInt       ttripC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1428                                      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,
1429                                      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,
1430                                      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,
1431                                      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,    2, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 1,
1432                                      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,
1433                                      DM_POLYTOPE_QUADRILATERAL, 1, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 1, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 0,    2, DM_POLYTOPE_SEG_PRISM_TENSOR, 0,    1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0};
1434   static PetscInt       ttripO[]  = {0, 0,
1435                                      0, 0, 0, 0,
1436                                      0, 0, 0, 0,
1437                                      0, 0, 0, 0,
1438                                      0, 0, 0,  0, -1, 0,
1439                                      0, 0, 0,  0,  0, -1,
1440                                      0, 0, 0, -1,  0, 0};
1441   /* TODO Add 3 quads inside every tensor triangular prism, making 4 new triangular prisms.
1442       2
1443       |\
1444       | \
1445       |  \
1446       0---1
1447 
1448       2
1449 
1450       0   1
1451 
1452       2
1453       |\
1454       | \
1455       |  \
1456       0---1
1457   */
1458   static DMPolytopeType ctripT[]  = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1459   static PetscInt       ctripS[]  = {1, 3, 3};
1460   static PetscInt       ctripC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1461                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1462                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0,
1463                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 4, 0,
1464                                      DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 0,    2, DM_POLYTOPE_QUADRILATERAL, 0,    0, DM_POLYTOPE_QUADRILATERAL, 1, 4, 1,
1465                                      DM_POLYTOPE_QUADRILATERAL, 1, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 1, 1, DM_POLYTOPE_QUADRILATERAL, 1, 2, 1, DM_POLYTOPE_QUADRILATERAL, 0,    1, DM_POLYTOPE_QUADRILATERAL, 1,  3, 0, DM_POLYTOPE_QUADRILATERAL, 0,    0,
1466                                      DM_POLYTOPE_QUADRILATERAL, 1, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 1, 2, DM_POLYTOPE_QUADRILATERAL, 0,    2, DM_POLYTOPE_QUADRILATERAL, 1, 3, 1, DM_POLYTOPE_QUADRILATERAL, 0,    1, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0};
1467   static PetscInt       ctripO[]  = {0, 0,
1468                                      0, 0, -2, -2,
1469                                      0, 0, -2, -2,
1470                                      0, 0, -2, -2,
1471                                     -4, 0, 0, -1,  0,  1,
1472                                     -4, 0, 0,  0,  0, -4,
1473                                     -4, 0, 0,  0, -1,  1};
1474   /* Add 1 edge and 4 quads inside every tensor quad prism, making 4 new hexahedra. */
1475   static DMPolytopeType tquadpT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
1476   static PetscInt       tquadpS[]  = {1, 4, 4};
1477   static PetscInt       tquadpC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1478                                       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,
1479                                       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,
1480                                       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,
1481                                       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,
1482                                       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,
1483                                       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,
1484                                       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,
1485                                       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};
1486   static PetscInt       tquadpO[]  = {0, 0,
1487                                       0, 0, 0, 0,
1488                                       0, 0, 0, 0,
1489                                       0, 0, 0, 0,
1490                                       0, 0, 0, 0,
1491                                       0, 0,  0,  0, -1,  0,
1492                                       0, 0,  0,  0,  0, -1,
1493                                       0, 0, -1,  0,  0,  0,
1494                                       0, 0,  0, -1,  0,  0};
1495   PetscBool convertTensor = PETSC_TRUE;
1496 
1497   PetscFunctionBeginHot;
1498   if (rt) *rt = 0;
1499   if (convertTensor) {
1500     switch (source) {
1501       case DM_POLYTOPE_POINT:
1502       case DM_POLYTOPE_SEGMENT:
1503       case DM_POLYTOPE_QUADRILATERAL:
1504       case DM_POLYTOPE_HEXAHEDRON:
1505         ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1506         break;
1507       case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT;  *size = tedgeS;  *cone = tedgeC;  *ornt = tedgeO;  break;
1508       case DM_POLYTOPE_SEG_PRISM_TENSOR:   *Nt = 2; *target = tquadT;  *size = tquadS;  *cone = tquadC;  *ornt = tquadO;  break;
1509       case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 3; *target = ctripT;  *size = ctripS;  *cone = ctripC;  *ornt = ctripO;  break;
1510       case DM_POLYTOPE_QUAD_PRISM_TENSOR:  *Nt = 3; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break;
1511       case DM_POLYTOPE_TRIANGLE:           *Nt = 3; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1512       case DM_POLYTOPE_TETRAHEDRON:        *Nt = 4; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1513       case DM_POLYTOPE_TRI_PRISM:          *Nt = 4; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
1514       /* TODO Fix pyramids: For now, we just ignore them */
1515       case DM_POLYTOPE_PYRAMID:
1516         ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1517         break;
1518       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1519     }
1520   } else {
1521     switch (source) {
1522       case DM_POLYTOPE_POINT:
1523       case DM_POLYTOPE_POINT_PRISM_TENSOR:
1524       case DM_POLYTOPE_SEGMENT:
1525       case DM_POLYTOPE_QUADRILATERAL:
1526       case DM_POLYTOPE_SEG_PRISM_TENSOR:
1527       case DM_POLYTOPE_HEXAHEDRON:
1528       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
1529         ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1530         break;
1531       case DM_POLYTOPE_TRIANGLE:           *Nt = 3; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1532       case DM_POLYTOPE_TETRAHEDRON:        *Nt = 4; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1533       case DM_POLYTOPE_TRI_PRISM:          *Nt = 4; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
1534       case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 3; *target = ttripT;  *size = ttripS;  *cone = ttripC;  *ornt = ttripO;  break;
1535       /* TODO Fix pyramids: For now, we just ignore them */
1536       case DM_POLYTOPE_PYRAMID:
1537         ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1538         break;
1539       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1540     }
1541   }
1542   PetscFunctionReturn(0);
1543 }
1544 
1545 static PetscErrorCode DMPlexCellRefinerRefine_ToSimplex(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
1546 {
1547   PetscErrorCode ierr;
1548 
1549   PetscFunctionBeginHot;
1550   if (rt) *rt = 0;
1551   switch (source) {
1552     case DM_POLYTOPE_POINT:
1553     case DM_POLYTOPE_SEGMENT:
1554     case DM_POLYTOPE_POINT_PRISM_TENSOR:
1555     case DM_POLYTOPE_TRIANGLE:
1556     case DM_POLYTOPE_TETRAHEDRON:
1557     case DM_POLYTOPE_TRI_PRISM:
1558     case DM_POLYTOPE_TRI_PRISM_TENSOR:
1559     case DM_POLYTOPE_QUADRILATERAL:
1560     case DM_POLYTOPE_SEG_PRISM_TENSOR:
1561     case DM_POLYTOPE_HEXAHEDRON:
1562     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
1563       ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1564       break;
1565     /* TODO Fix pyramids: For now, we just ignore them */
1566     case DM_POLYTOPE_PYRAMID:
1567       ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1568       break;
1569     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1570   }
1571   PetscFunctionReturn(0);
1572 }
1573 
1574 static PetscErrorCode DMPlexCellRefinerRefine_Alfeld2D(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
1575 {
1576   PetscErrorCode ierr;
1577   /* Add 1 vertex, 3 edges inside every triangle, making 3 new triangles.
1578    2
1579    |\
1580    |\\
1581    | |\
1582    | \ \
1583    | |  \
1584    |  \  \
1585    |   |  \
1586    2   \   \
1587    |   |    1
1588    |   2    \
1589    |   |    \
1590    |   /\   \
1591    |  0  1  |
1592    | /    \ |
1593    |/      \|
1594    0---0----1
1595   */
1596   static DMPolytopeType triT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE};
1597   static PetscInt       triS[]    = {1, 3, 3};
1598   static PetscInt       triC[]    = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1599                                      DM_POLYTOPE_POINT, 2, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1600                                      DM_POLYTOPE_POINT, 2, 2, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1601                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 0,
1602                                      DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 1,
1603                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 2};
1604   static PetscInt       triO[]    = {0, 0,
1605                                      0, 0,
1606                                      0, 0,
1607                                      0,  0, -2,
1608                                      0,  0, -2,
1609                                      0,  0, -2};
1610 
1611   PetscFunctionBeginHot;
1612   if (rt) *rt = 0;
1613   switch (source) {
1614     case DM_POLYTOPE_POINT:
1615     case DM_POLYTOPE_SEGMENT:
1616     case DM_POLYTOPE_POINT_PRISM_TENSOR:
1617     case DM_POLYTOPE_QUADRILATERAL:
1618     case DM_POLYTOPE_SEG_PRISM_TENSOR:
1619     case DM_POLYTOPE_TETRAHEDRON:
1620     case DM_POLYTOPE_HEXAHEDRON:
1621     case DM_POLYTOPE_TRI_PRISM:
1622     case DM_POLYTOPE_TRI_PRISM_TENSOR:
1623     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
1624     case DM_POLYTOPE_PYRAMID:
1625       ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1626       break;
1627     case DM_POLYTOPE_TRIANGLE:           *Nt = 3; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1628     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1629   }
1630   PetscFunctionReturn(0);
1631 }
1632 
1633 static PetscErrorCode DMPlexCellRefinerRefine_Alfeld3D(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
1634 {
1635   PetscErrorCode ierr;
1636   /* Add 6 triangles inside every cell, making 4 new tets
1637      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
1638      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]
1639      called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are
1640        [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3]
1641      We make a new tet on each face
1642        [v0, v1, v2, (c0, 0)]
1643        [v0, v3, v1, (c0, 0)]
1644        [v0, v2, v3, (c0, 0)]
1645        [v2, v1, v3, (c0, 0)]
1646      We create a new face for each edge
1647        [v0, (c0, 0), v1     ]
1648        [v0, v2,      (c0, 0)]
1649        [v2, v1,      (c0, 0)]
1650        [v0, (c0, 0), v3     ]
1651        [v1, v3,      (c0, 0)]
1652        [v3, v2,      (c0, 0)]
1653    */
1654   static DMPolytopeType tetT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_TETRAHEDRON};
1655   static PetscInt       tetS[]    = {1, 4, 6, 4};
1656   static PetscInt       tetC[]    = {DM_POLYTOPE_POINT, 3, 0, 0, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1657                                      DM_POLYTOPE_POINT, 3, 0, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1658                                      DM_POLYTOPE_POINT, 3, 0, 2, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1659                                      DM_POLYTOPE_POINT, 3, 1, 0, 1, 0, DM_POLYTOPE_POINT, 0, 0,
1660                                      DM_POLYTOPE_SEGMENT, 0,       0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 2, 0, 0, 0,
1661                                      DM_POLYTOPE_SEGMENT, 2, 0, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,       0,
1662                                      DM_POLYTOPE_SEGMENT, 2, 0, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,       2,
1663                                      DM_POLYTOPE_SEGMENT, 0,       0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 2, 1, 0, 0,
1664                                      DM_POLYTOPE_SEGMENT, 2, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,       1,
1665                                      DM_POLYTOPE_SEGMENT, 2, 2, 1, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,       3,
1666                                      DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 0, 0, DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_TRIANGLE, 0, 2,
1667                                      DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_TRIANGLE, 0, 0, DM_POLYTOPE_TRIANGLE, 0, 4,
1668                                      DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_TRIANGLE, 0, 5,
1669                                      DM_POLYTOPE_TRIANGLE, 1, 3, 0, DM_POLYTOPE_TRIANGLE, 0, 2, DM_POLYTOPE_TRIANGLE, 0, 5, DM_POLYTOPE_TRIANGLE, 0, 4};
1670   static PetscInt       tetO[]    = {0, 0,
1671                                      0, 0,
1672                                      0, 0,
1673                                      0, 0,
1674                                      0, -2, -2,
1675                                     -2,  0, -2,
1676                                     -2,  0, -2,
1677                                      0, -2, -2,
1678                                     -2,  0, -2,
1679                                     -2,  0, -2,
1680                                      0,  0,  0,  0,
1681                                      0,  0, -3,  0,
1682                                      0, -3, -3,  0,
1683                                      0, -3, -1, -1};
1684 
1685   PetscFunctionBeginHot;
1686   if (rt) *rt = 0;
1687   switch (source) {
1688     case DM_POLYTOPE_POINT:
1689     case DM_POLYTOPE_SEGMENT:
1690     case DM_POLYTOPE_POINT_PRISM_TENSOR:
1691     case DM_POLYTOPE_TRIANGLE:
1692     case DM_POLYTOPE_QUADRILATERAL:
1693     case DM_POLYTOPE_SEG_PRISM_TENSOR:
1694     case DM_POLYTOPE_HEXAHEDRON:
1695     case DM_POLYTOPE_TRI_PRISM:
1696     case DM_POLYTOPE_TRI_PRISM_TENSOR:
1697     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
1698     case DM_POLYTOPE_PYRAMID:
1699       ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1700       break;
1701     case DM_POLYTOPE_TETRAHEDRON:        *Nt = 4; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1702     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1703   }
1704   PetscFunctionReturn(0);
1705 }
1706 
1707 typedef struct {
1708   PetscInt       n;
1709   PetscReal      r;
1710   PetscScalar    *h;
1711   PetscInt       *Nt;
1712   DMPolytopeType **target;
1713   PetscInt       **size;
1714   PetscInt       **cone;
1715   PetscInt       **ornt;
1716 } PlexRefiner_BL;
1717 
1718 static PetscErrorCode DMPlexCellRefinerSetUp_BL(DMPlexCellRefiner cr)
1719 {
1720   PlexRefiner_BL *crbl;
1721   PetscErrorCode ierr;
1722   PetscInt       i,n;
1723   PetscReal      r;
1724   PetscInt       c1,c2,o1,o2;
1725 
1726   PetscFunctionBegin;
1727   ierr = PetscNew(&crbl);CHKERRQ(ierr);
1728   cr->data = crbl;
1729   crbl->n = 1; /* 1 split -> 2 new cells */
1730   crbl->r = 1; /* linear progression */
1731 
1732   /* TODO: add setfromoptions to the refiners? */
1733   ierr = PetscOptionsGetInt(((PetscObject) cr->dm)->options,((PetscObject) cr->dm)->prefix, "-dm_plex_refine_boundarylayer_splits", &crbl->n, NULL);CHKERRQ(ierr);
1734   if (crbl->n < 1) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Number of splits %D must be positive",crbl->n);
1735   ierr = PetscOptionsGetReal(((PetscObject) cr->dm)->options,((PetscObject) cr->dm)->prefix, "-dm_plex_refine_boundarylayer_progression", &crbl->r, NULL);CHKERRQ(ierr);
1736   n = crbl->n;
1737   r = crbl->r;
1738 
1739   /* we only split DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_TRI_PRISM_TENSOR and DM_POLYTOPE_QUAD_PRISM_TENSOR */
1740   ierr = PetscMalloc5(4,&crbl->Nt,4,&crbl->target,4,&crbl->size,4,&crbl->cone,4,&crbl->ornt);CHKERRQ(ierr);
1741 
1742   /* progression */
1743   ierr = PetscMalloc1(n,&crbl->h);CHKERRQ(ierr);
1744   if (r > 1) {
1745     PetscReal d = (r-1.)/(PetscPowRealInt(r,n+1)-1.);
1746 
1747     crbl->h[0] = d;
1748     for (i = 1; i < n; i++) {
1749       d *= r;
1750       crbl->h[i] = crbl->h[i-1] + d;
1751     }
1752   } else { /* linear */
1753     for (i = 0; i < n; i++) crbl->h[i] = (i + 1.)/(n+1); /* linear */
1754   }
1755 
1756   /* DM_POLYTOPE_POINT_PRISM_TENSOR produces n points and n+1 tensor segments */
1757   c1 = 14+6*(n-1);
1758   o1 = 2*(n+1);
1759   crbl->Nt[0] = 2;
1760 
1761   ierr = PetscMalloc4(crbl->Nt[0],&crbl->target[0],crbl->Nt[0],&crbl->size[0],c1,&crbl->cone[0],o1,&crbl->ornt[0]);CHKERRQ(ierr);
1762 
1763   crbl->target[0][0] = DM_POLYTOPE_POINT;
1764   crbl->target[0][1] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1765 
1766   crbl->size[0][0] = n;
1767   crbl->size[0][1] = n+1;
1768 
1769   /* the tensor segments */
1770   crbl->cone[0][0] = DM_POLYTOPE_POINT;
1771   crbl->cone[0][1] = 1;
1772   crbl->cone[0][2] = 0;
1773   crbl->cone[0][3] = 0;
1774   crbl->cone[0][4] = DM_POLYTOPE_POINT;
1775   crbl->cone[0][5] = 0;
1776   crbl->cone[0][6] = 0;
1777   for (i = 0; i < n-1; i++) {
1778     crbl->cone[0][7+6*i+0] = DM_POLYTOPE_POINT;
1779     crbl->cone[0][7+6*i+1] = 0;
1780     crbl->cone[0][7+6*i+2] = i;
1781     crbl->cone[0][7+6*i+3] = DM_POLYTOPE_POINT;
1782     crbl->cone[0][7+6*i+4] = 0;
1783     crbl->cone[0][7+6*i+5] = i+1;
1784   }
1785   crbl->cone[0][7+6*(n-1)+0] = DM_POLYTOPE_POINT;
1786   crbl->cone[0][7+6*(n-1)+1] = 0;
1787   crbl->cone[0][7+6*(n-1)+2] = n-1;
1788   crbl->cone[0][7+6*(n-1)+3] = DM_POLYTOPE_POINT;
1789   crbl->cone[0][7+6*(n-1)+4] = 1;
1790   crbl->cone[0][7+6*(n-1)+5] = 1;
1791   crbl->cone[0][7+6*(n-1)+6] = 0;
1792   for (i = 0; i < o1; i++) crbl->ornt[0][i] = 0;
1793 
1794   /* DM_POLYTOPE_SEG_PRISM_TENSOR produces n segments and n+1 tensor quads */
1795   c1 = 8*n;
1796   c2 = 30+14*(n-1);
1797   o1 = 2*n;
1798   o2 = 4*(n+1);
1799   crbl->Nt[1] = 2;
1800 
1801   ierr = PetscMalloc4(crbl->Nt[1],&crbl->target[1],crbl->Nt[1],&crbl->size[1],c1+c2,&crbl->cone[1],o1+o2,&crbl->ornt[1]);CHKERRQ(ierr);
1802 
1803   crbl->target[1][0] = DM_POLYTOPE_SEGMENT;
1804   crbl->target[1][1] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1805 
1806   crbl->size[1][0] = n;
1807   crbl->size[1][1] = n+1;
1808 
1809   /* the segments */
1810   for (i = 0; i < n; i++) {
1811     crbl->cone[1][8*i+0] = DM_POLYTOPE_POINT;
1812     crbl->cone[1][8*i+1] = 1;
1813     crbl->cone[1][8*i+2] = 2;
1814     crbl->cone[1][8*i+3] = i;
1815     crbl->cone[1][8*i+4] = DM_POLYTOPE_POINT;
1816     crbl->cone[1][8*i+5] = 1;
1817     crbl->cone[1][8*i+6] = 3;
1818     crbl->cone[1][8*i+7] = i;
1819   }
1820 
1821   /* the tensor quads */
1822   crbl->cone[1][c1+ 0] = DM_POLYTOPE_SEGMENT;
1823   crbl->cone[1][c1+ 1] = 1;
1824   crbl->cone[1][c1+ 2] = 0;
1825   crbl->cone[1][c1+ 3] = 0;
1826   crbl->cone[1][c1+ 4] = DM_POLYTOPE_SEGMENT;
1827   crbl->cone[1][c1+ 5] = 0;
1828   crbl->cone[1][c1+ 6] = 0;
1829   crbl->cone[1][c1+ 7] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1830   crbl->cone[1][c1+ 8] = 1;
1831   crbl->cone[1][c1+ 9] = 2;
1832   crbl->cone[1][c1+10] = 0;
1833   crbl->cone[1][c1+11] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1834   crbl->cone[1][c1+12] = 1;
1835   crbl->cone[1][c1+13] = 3;
1836   crbl->cone[1][c1+14] = 0;
1837   for (i = 0; i < n-1; i++) {
1838     crbl->cone[1][c1+15+14*i+ 0] = DM_POLYTOPE_SEGMENT;
1839     crbl->cone[1][c1+15+14*i+ 1] = 0;
1840     crbl->cone[1][c1+15+14*i+ 2] = i;
1841     crbl->cone[1][c1+15+14*i+ 3] = DM_POLYTOPE_SEGMENT;
1842     crbl->cone[1][c1+15+14*i+ 4] = 0;
1843     crbl->cone[1][c1+15+14*i+ 5] = i+1;
1844     crbl->cone[1][c1+15+14*i+ 6] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1845     crbl->cone[1][c1+15+14*i+ 7] = 1;
1846     crbl->cone[1][c1+15+14*i+ 8] = 2;
1847     crbl->cone[1][c1+15+14*i+ 9] = i+1;
1848     crbl->cone[1][c1+15+14*i+10] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1849     crbl->cone[1][c1+15+14*i+11] = 1;
1850     crbl->cone[1][c1+15+14*i+12] = 3;
1851     crbl->cone[1][c1+15+14*i+13] = i+1;
1852   }
1853   crbl->cone[1][c1+15+14*(n-1)+ 0] = DM_POLYTOPE_SEGMENT;
1854   crbl->cone[1][c1+15+14*(n-1)+ 1] = 0;
1855   crbl->cone[1][c1+15+14*(n-1)+ 2] = n-1;
1856   crbl->cone[1][c1+15+14*(n-1)+ 3] = DM_POLYTOPE_SEGMENT;
1857   crbl->cone[1][c1+15+14*(n-1)+ 4] = 1;
1858   crbl->cone[1][c1+15+14*(n-1)+ 5] = 1;
1859   crbl->cone[1][c1+15+14*(n-1)+ 6] = 0;
1860   crbl->cone[1][c1+15+14*(n-1)+ 7] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1861   crbl->cone[1][c1+15+14*(n-1)+ 8] = 1;
1862   crbl->cone[1][c1+15+14*(n-1)+ 9] = 2;
1863   crbl->cone[1][c1+15+14*(n-1)+10] = n;
1864   crbl->cone[1][c1+15+14*(n-1)+11] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1865   crbl->cone[1][c1+15+14*(n-1)+12] = 1;
1866   crbl->cone[1][c1+15+14*(n-1)+13] = 3;
1867   crbl->cone[1][c1+15+14*(n-1)+14] = n;
1868   for (i = 0; i < o1+o2; i++) crbl->ornt[1][i] = 0;
1869 
1870   /* DM_POLYTOPE_TRI_PRISM_TENSOR produces n triangles and n+1 tensor triangular prisms */
1871   c1 = 12*n;
1872   c2 = 38+18*(n-1);
1873   o1 = 3*n;
1874   o2 = 5*(n+1);
1875   crbl->Nt[2] = 2;
1876 
1877   ierr = PetscMalloc4(crbl->Nt[2],&crbl->target[2],crbl->Nt[2],&crbl->size[2],c1+c2,&crbl->cone[2],o1+o2,&crbl->ornt[2]);CHKERRQ(ierr);
1878 
1879   crbl->target[2][0] = DM_POLYTOPE_TRIANGLE;
1880   crbl->target[2][1] = DM_POLYTOPE_TRI_PRISM_TENSOR;
1881 
1882   crbl->size[2][0] = n;
1883   crbl->size[2][1] = n+1;
1884 
1885   /* the triangles */
1886   for (i = 0; i < n; i++) {
1887     crbl->cone[2][12*i+ 0] = DM_POLYTOPE_SEGMENT;
1888     crbl->cone[2][12*i+ 1] = 1;
1889     crbl->cone[2][12*i+ 2] = 2;
1890     crbl->cone[2][12*i+ 3] = i;
1891     crbl->cone[2][12*i+ 4] = DM_POLYTOPE_SEGMENT;
1892     crbl->cone[2][12*i+ 5] = 1;
1893     crbl->cone[2][12*i+ 6] = 3;
1894     crbl->cone[2][12*i+ 7] = i;
1895     crbl->cone[2][12*i+ 8] = DM_POLYTOPE_SEGMENT;
1896     crbl->cone[2][12*i+ 9] = 1;
1897     crbl->cone[2][12*i+10] = 4;
1898     crbl->cone[2][12*i+11] = i;
1899   }
1900 
1901   /* the triangular prisms */
1902   crbl->cone[2][c1+ 0] = DM_POLYTOPE_TRIANGLE;
1903   crbl->cone[2][c1+ 1] = 1;
1904   crbl->cone[2][c1+ 2] = 0;
1905   crbl->cone[2][c1+ 3] = 0;
1906   crbl->cone[2][c1+ 4] = DM_POLYTOPE_TRIANGLE;
1907   crbl->cone[2][c1+ 5] = 0;
1908   crbl->cone[2][c1+ 6] = 0;
1909   crbl->cone[2][c1+ 7] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1910   crbl->cone[2][c1+ 8] = 1;
1911   crbl->cone[2][c1+ 9] = 2;
1912   crbl->cone[2][c1+10] = 0;
1913   crbl->cone[2][c1+11] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1914   crbl->cone[2][c1+12] = 1;
1915   crbl->cone[2][c1+13] = 3;
1916   crbl->cone[2][c1+14] = 0;
1917   crbl->cone[2][c1+15] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1918   crbl->cone[2][c1+16] = 1;
1919   crbl->cone[2][c1+17] = 4;
1920   crbl->cone[2][c1+18] = 0;
1921   for (i = 0; i < n-1; i++) {
1922     crbl->cone[2][c1+19+18*i+ 0] = DM_POLYTOPE_TRIANGLE;
1923     crbl->cone[2][c1+19+18*i+ 1] = 0;
1924     crbl->cone[2][c1+19+18*i+ 2] = i;
1925     crbl->cone[2][c1+19+18*i+ 3] = DM_POLYTOPE_TRIANGLE;
1926     crbl->cone[2][c1+19+18*i+ 4] = 0;
1927     crbl->cone[2][c1+19+18*i+ 5] = i+1;
1928     crbl->cone[2][c1+19+18*i+ 6] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1929     crbl->cone[2][c1+19+18*i+ 7] = 1;
1930     crbl->cone[2][c1+19+18*i+ 8] = 2;
1931     crbl->cone[2][c1+19+18*i+ 9] = i+1;
1932     crbl->cone[2][c1+19+18*i+10] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1933     crbl->cone[2][c1+19+18*i+11] = 1;
1934     crbl->cone[2][c1+19+18*i+12] = 3;
1935     crbl->cone[2][c1+19+18*i+13] = i+1;
1936     crbl->cone[2][c1+19+18*i+14] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1937     crbl->cone[2][c1+19+18*i+15] = 1;
1938     crbl->cone[2][c1+19+18*i+16] = 4;
1939     crbl->cone[2][c1+19+18*i+17] = i+1;
1940   }
1941   crbl->cone[2][c1+19+18*(n-1)+ 0] = DM_POLYTOPE_TRIANGLE;
1942   crbl->cone[2][c1+19+18*(n-1)+ 1] = 0;
1943   crbl->cone[2][c1+19+18*(n-1)+ 2] = n-1;
1944   crbl->cone[2][c1+19+18*(n-1)+ 3] = DM_POLYTOPE_TRIANGLE;
1945   crbl->cone[2][c1+19+18*(n-1)+ 4] = 1;
1946   crbl->cone[2][c1+19+18*(n-1)+ 5] = 1;
1947   crbl->cone[2][c1+19+18*(n-1)+ 6] = 0;
1948   crbl->cone[2][c1+19+18*(n-1)+ 7] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1949   crbl->cone[2][c1+19+18*(n-1)+ 8] = 1;
1950   crbl->cone[2][c1+19+18*(n-1)+ 9] = 2;
1951   crbl->cone[2][c1+19+18*(n-1)+10] = n;
1952   crbl->cone[2][c1+19+18*(n-1)+11] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1953   crbl->cone[2][c1+19+18*(n-1)+12] = 1;
1954   crbl->cone[2][c1+19+18*(n-1)+13] = 3;
1955   crbl->cone[2][c1+19+18*(n-1)+14] = n;
1956   crbl->cone[2][c1+19+18*(n-1)+15] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1957   crbl->cone[2][c1+19+18*(n-1)+16] = 1;
1958   crbl->cone[2][c1+19+18*(n-1)+17] = 4;
1959   crbl->cone[2][c1+19+18*(n-1)+18] = n;
1960   for (i = 0; i < o1+o2; i++) crbl->ornt[2][i] = 0;
1961 
1962   /* DM_POLYTOPE_QUAD_PRISM_TENSOR produces n quads and n+1 tensor quad prisms */
1963   c1 = 16*n;
1964   c2 = 46+22*(n-1);
1965   o1 = 4*n;
1966   o2 = 6*(n+1);
1967   crbl->Nt[3] = 2;
1968 
1969   ierr = PetscMalloc4(crbl->Nt[3],&crbl->target[3],crbl->Nt[3],&crbl->size[3],c1+c2,&crbl->cone[3],o1+o2,&crbl->ornt[3]);CHKERRQ(ierr);
1970 
1971   crbl->target[3][0] = DM_POLYTOPE_QUADRILATERAL;
1972   crbl->target[3][1] = DM_POLYTOPE_QUAD_PRISM_TENSOR;
1973 
1974   crbl->size[3][0] = n;
1975   crbl->size[3][1] = n+1;
1976 
1977   /* the quads */
1978   for (i = 0; i < n; i++) {
1979     crbl->cone[3][16*i+ 0] = DM_POLYTOPE_SEGMENT;
1980     crbl->cone[3][16*i+ 1] = 1;
1981     crbl->cone[3][16*i+ 2] = 2;
1982     crbl->cone[3][16*i+ 3] = i;
1983     crbl->cone[3][16*i+ 4] = DM_POLYTOPE_SEGMENT;
1984     crbl->cone[3][16*i+ 5] = 1;
1985     crbl->cone[3][16*i+ 6] = 3;
1986     crbl->cone[3][16*i+ 7] = i;
1987     crbl->cone[3][16*i+ 8] = DM_POLYTOPE_SEGMENT;
1988     crbl->cone[3][16*i+ 9] = 1;
1989     crbl->cone[3][16*i+10] = 4;
1990     crbl->cone[3][16*i+11] = i;
1991     crbl->cone[3][16*i+12] = DM_POLYTOPE_SEGMENT;
1992     crbl->cone[3][16*i+13] = 1;
1993     crbl->cone[3][16*i+14] = 5;
1994     crbl->cone[3][16*i+15] = i;
1995   }
1996 
1997   /* the quad prisms */
1998   crbl->cone[3][c1+ 0] = DM_POLYTOPE_QUADRILATERAL;
1999   crbl->cone[3][c1+ 1] = 1;
2000   crbl->cone[3][c1+ 2] = 0;
2001   crbl->cone[3][c1+ 3] = 0;
2002   crbl->cone[3][c1+ 4] = DM_POLYTOPE_QUADRILATERAL;
2003   crbl->cone[3][c1+ 5] = 0;
2004   crbl->cone[3][c1+ 6] = 0;
2005   crbl->cone[3][c1+ 7] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2006   crbl->cone[3][c1+ 8] = 1;
2007   crbl->cone[3][c1+ 9] = 2;
2008   crbl->cone[3][c1+10] = 0;
2009   crbl->cone[3][c1+11] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2010   crbl->cone[3][c1+12] = 1;
2011   crbl->cone[3][c1+13] = 3;
2012   crbl->cone[3][c1+14] = 0;
2013   crbl->cone[3][c1+15] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2014   crbl->cone[3][c1+16] = 1;
2015   crbl->cone[3][c1+17] = 4;
2016   crbl->cone[3][c1+18] = 0;
2017   crbl->cone[3][c1+19] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2018   crbl->cone[3][c1+20] = 1;
2019   crbl->cone[3][c1+21] = 5;
2020   crbl->cone[3][c1+22] = 0;
2021   for (i = 0; i < n-1; i++) {
2022     crbl->cone[3][c1+23+22*i+ 0] = DM_POLYTOPE_QUADRILATERAL;
2023     crbl->cone[3][c1+23+22*i+ 1] = 0;
2024     crbl->cone[3][c1+23+22*i+ 2] = i;
2025     crbl->cone[3][c1+23+22*i+ 3] = DM_POLYTOPE_QUADRILATERAL;
2026     crbl->cone[3][c1+23+22*i+ 4] = 0;
2027     crbl->cone[3][c1+23+22*i+ 5] = i+1;
2028     crbl->cone[3][c1+23+22*i+ 6] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2029     crbl->cone[3][c1+23+22*i+ 7] = 1;
2030     crbl->cone[3][c1+23+22*i+ 8] = 2;
2031     crbl->cone[3][c1+23+22*i+ 9] = i+1;
2032     crbl->cone[3][c1+23+22*i+10] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2033     crbl->cone[3][c1+23+22*i+11] = 1;
2034     crbl->cone[3][c1+23+22*i+12] = 3;
2035     crbl->cone[3][c1+23+22*i+13] = i+1;
2036     crbl->cone[3][c1+23+22*i+14] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2037     crbl->cone[3][c1+23+22*i+15] = 1;
2038     crbl->cone[3][c1+23+22*i+16] = 4;
2039     crbl->cone[3][c1+23+22*i+17] = i+1;
2040     crbl->cone[3][c1+23+22*i+18] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2041     crbl->cone[3][c1+23+22*i+19] = 1;
2042     crbl->cone[3][c1+23+22*i+20] = 5;
2043     crbl->cone[3][c1+23+22*i+21] = i+1;
2044   }
2045   crbl->cone[3][c1+23+22*(n-1)+ 0] = DM_POLYTOPE_QUADRILATERAL;
2046   crbl->cone[3][c1+23+22*(n-1)+ 1] = 0;
2047   crbl->cone[3][c1+23+22*(n-1)+ 2] = n-1;
2048   crbl->cone[3][c1+23+22*(n-1)+ 3] = DM_POLYTOPE_QUADRILATERAL;
2049   crbl->cone[3][c1+23+22*(n-1)+ 4] = 1;
2050   crbl->cone[3][c1+23+22*(n-1)+ 5] = 1;
2051   crbl->cone[3][c1+23+22*(n-1)+ 6] = 0;
2052   crbl->cone[3][c1+23+22*(n-1)+ 7] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2053   crbl->cone[3][c1+23+22*(n-1)+ 8] = 1;
2054   crbl->cone[3][c1+23+22*(n-1)+ 9] = 2;
2055   crbl->cone[3][c1+23+22*(n-1)+10] = n;
2056   crbl->cone[3][c1+23+22*(n-1)+11] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2057   crbl->cone[3][c1+23+22*(n-1)+12] = 1;
2058   crbl->cone[3][c1+23+22*(n-1)+13] = 3;
2059   crbl->cone[3][c1+23+22*(n-1)+14] = n;
2060   crbl->cone[3][c1+23+22*(n-1)+15] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2061   crbl->cone[3][c1+23+22*(n-1)+16] = 1;
2062   crbl->cone[3][c1+23+22*(n-1)+17] = 4;
2063   crbl->cone[3][c1+23+22*(n-1)+18] = n;
2064   crbl->cone[3][c1+23+22*(n-1)+19] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2065   crbl->cone[3][c1+23+22*(n-1)+20] = 1;
2066   crbl->cone[3][c1+23+22*(n-1)+21] = 5;
2067   crbl->cone[3][c1+23+22*(n-1)+22] = n;
2068   for (i = 0; i < o1+o2; i++) crbl->ornt[3][i] = 0;
2069   PetscFunctionReturn(0);
2070 }
2071 
2072 static PetscErrorCode DMPlexCellRefinerDestroy_BL(DMPlexCellRefiner cr)
2073 {
2074   PlexRefiner_BL *crbl = (PlexRefiner_BL *)cr->data;
2075   PetscErrorCode ierr;
2076 
2077   PetscFunctionBegin;
2078   ierr = PetscFree4(crbl->target[0],crbl->size[0],crbl->cone[0],crbl->ornt[0]);CHKERRQ(ierr);
2079   ierr = PetscFree4(crbl->target[1],crbl->size[1],crbl->cone[1],crbl->ornt[1]);CHKERRQ(ierr);
2080   ierr = PetscFree4(crbl->target[2],crbl->size[2],crbl->cone[2],crbl->ornt[2]);CHKERRQ(ierr);
2081   ierr = PetscFree4(crbl->target[3],crbl->size[3],crbl->cone[3],crbl->ornt[3]);CHKERRQ(ierr);
2082   ierr = PetscFree5(crbl->Nt,crbl->target,crbl->size,crbl->cone,crbl->ornt);CHKERRQ(ierr);
2083   ierr = PetscFree(crbl->h);CHKERRQ(ierr);
2084   ierr = PetscFree(cr->data);CHKERRQ(ierr);
2085   PetscFunctionReturn(0);
2086 }
2087 
2088 static PetscErrorCode DMPlexCellRefinerRefine_BL(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
2089 {
2090   PlexRefiner_BL  *crbl = (PlexRefiner_BL *)cr->data;
2091   PetscErrorCode  ierr;
2092 
2093   PetscFunctionBeginHot;
2094   if (rt) *rt = 0;
2095   switch (source) {
2096   case DM_POLYTOPE_POINT_PRISM_TENSOR:
2097     *Nt     = crbl->Nt[0];
2098     *target = crbl->target[0];
2099     *size   = crbl->size[0];
2100     *cone   = crbl->cone[0];
2101     *ornt   = crbl->ornt[0];
2102     break;
2103   case DM_POLYTOPE_SEG_PRISM_TENSOR:
2104     *Nt     = crbl->Nt[1];
2105     *target = crbl->target[1];
2106     *size   = crbl->size[1];
2107     *cone   = crbl->cone[1];
2108     *ornt   = crbl->ornt[1];
2109     break;
2110   case DM_POLYTOPE_TRI_PRISM_TENSOR:
2111     *Nt     = crbl->Nt[2];
2112     *target = crbl->target[2];
2113     *size   = crbl->size[2];
2114     *cone   = crbl->cone[2];
2115     *ornt   = crbl->ornt[2];
2116     break;
2117   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
2118     *Nt     = crbl->Nt[3];
2119     *target = crbl->target[3];
2120     *size   = crbl->size[3];
2121     *cone   = crbl->cone[3];
2122     *ornt   = crbl->ornt[3];
2123     break;
2124   default:
2125     ierr = DMPlexCellRefinerRefine_None(cr,source,p,rt,Nt,target,size,cone,ornt);CHKERRQ(ierr);
2126   }
2127   PetscFunctionReturn(0);
2128 }
2129 
2130 static PetscErrorCode DMPlexCellRefinerMapSubcells_BL(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
2131 {
2132   /* We shift any input orientation in order to make it non-negative
2133        The orientation array o[po][o] gives the orientation the new replica rnew has to have in order to reproduce the face sequence from (r, o)
2134        The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po
2135        Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po
2136   */
2137   PetscInt       tquad_seg_o[]   = { 0,  1, -2, -1,
2138                                      0,  1, -2, -1,
2139                                     -2, -1,  0,  1,
2140                                     -2, -1,  0,  1};
2141   PetscInt       tquad_tquad_o[] = { 0,  1, -2, -1,
2142                                      1,  0, -1, -2,
2143                                     -2, -1,  0,  1,
2144                                     -1, -2,  1,  0};
2145   PlexRefiner_BL *crbl = (PlexRefiner_BL *)cr->data;
2146   const PetscInt n = crbl->n;
2147   PetscErrorCode ierr;
2148 
2149   PetscFunctionBeginHot;
2150   *rnew = r;
2151   *onew = o;
2152   switch (pct) {
2153     case DM_POLYTOPE_POINT_PRISM_TENSOR:
2154       if (ct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
2155         if      (po == 0 || po == -1) {*rnew = r;     *onew = o;}
2156         else if (po == 1 || po == -2) {*rnew = n - r; *onew = (o == 0 || o == -1) ? -2 : 0;}
2157         else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid orientation %D for tensor segment", po);
2158       }
2159       break;
2160     case DM_POLYTOPE_SEG_PRISM_TENSOR:
2161       switch (ct) {
2162         case DM_POLYTOPE_SEGMENT:
2163           *onew = tquad_seg_o[(po+2)*4+o+2];
2164           *rnew = r;
2165           break;
2166         case DM_POLYTOPE_SEG_PRISM_TENSOR:
2167           *onew = tquad_tquad_o[(po+2)*4+o+2];
2168           *rnew = r;
2169           break;
2170         default: break;
2171       }
2172       break;
2173     default:
2174       ierr = DMPlexCellRefinerMapSubcells_None(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
2175   }
2176   PetscFunctionReturn(0);
2177 }
2178 
2179 static PetscErrorCode DMPlexCellRefinerMapCoordinates_BL(DMPlexCellRefiner cr, DMPolytopeType pct, DMPolytopeType ct, PetscInt r, PetscInt Nv, PetscInt dE, const PetscScalar in[], PetscScalar out[])
2180 {
2181   PlexRefiner_BL  *crbl = (PlexRefiner_BL *)cr->data;
2182   PetscInt        d;
2183   PetscErrorCode  ierr;
2184 
2185   PetscFunctionBeginHot;
2186   switch (pct) {
2187   case DM_POLYTOPE_POINT_PRISM_TENSOR:
2188     if (ct != DM_POLYTOPE_POINT) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for refined point type %s",DMPolytopeTypes[ct]);
2189     if (Nv != 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for parent vertices %D",Nv);
2190     if (r >= crbl->n || r < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Invalid replica %D, must be in [0,%D)",r,crbl->n);
2191     for (d = 0; d < dE; d++) out[d] = in[d] + crbl->h[r] * (in[d + dE] - in[d]);
2192     break;
2193   default:
2194     ierr = DMPlexCellRefinerMapCoordinates_Barycenter(cr,pct,ct,r,Nv,dE,in,out);CHKERRQ(ierr);
2195   }
2196   PetscFunctionReturn(0);
2197 }
2198 
2199 typedef struct {
2200   DMLabel      splitPoints; /* List of edges to be bisected (1) and cells to be divided (2) */
2201   PetscSection secEdgeLen;  /* Section for edge length field */
2202   PetscReal   *edgeLen;     /* Storage for edge length field */
2203   PetscInt    *splitArray;  /* Array for communication of split points label */
2204 } PlexRefiner_SBR;
2205 
2206 typedef struct _p_PointQueue *PointQueue;
2207 struct _p_PointQueue {
2208   PetscInt  size;   /* Size of the storage array */
2209   PetscInt *points; /* Array of mesh points */
2210   PetscInt  front;  /* Index of the front of the queue */
2211   PetscInt  back;   /* Index of the back of the queue */
2212   PetscInt  num;    /* Number of enqueued points */
2213 };
2214 
2215 static PetscErrorCode PointQueueCreate(PetscInt size, PointQueue *queue)
2216 {
2217   PointQueue     q;
2218   PetscErrorCode ierr;
2219 
2220   PetscFunctionBegin;
2221   if (size < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Queue size %D must be non-negative", size);
2222   ierr = PetscCalloc1(1, &q);CHKERRQ(ierr);
2223   q->size = size;
2224   ierr = PetscMalloc1(q->size, &q->points);CHKERRQ(ierr);
2225   q->num   = 0;
2226   q->front = 0;
2227   q->back  = q->size-1;
2228   *queue = q;
2229   PetscFunctionReturn(0);
2230 }
2231 
2232 static PetscErrorCode PointQueueDestroy(PointQueue *queue)
2233 {
2234   PointQueue     q = *queue;
2235   PetscErrorCode ierr;
2236 
2237   PetscFunctionBegin;
2238   ierr = PetscFree(q->points);CHKERRQ(ierr);
2239   ierr = PetscFree(q);CHKERRQ(ierr);
2240   *queue = NULL;
2241   PetscFunctionReturn(0);
2242 }
2243 
2244 static PetscErrorCode PointQueueEnsureSize(PointQueue queue)
2245 {
2246   PetscErrorCode ierr;
2247 
2248   PetscFunctionBegin;
2249   if (queue->num < queue->size) PetscFunctionReturn(0);
2250   queue->size *= 2;
2251   ierr = PetscRealloc(queue->size * sizeof(PetscInt), &queue->points);CHKERRQ(ierr);
2252   PetscFunctionReturn(0);
2253 }
2254 
2255 static PetscErrorCode PointQueueEnqueue(PointQueue queue, PetscInt p)
2256 {
2257   PetscErrorCode ierr;
2258 
2259   PetscFunctionBegin;
2260   ierr = PointQueueEnsureSize(queue);CHKERRQ(ierr);
2261   queue->back = (queue->back + 1) % queue->size;
2262   queue->points[queue->back] = p;
2263   ++queue->num;
2264   PetscFunctionReturn(0);
2265 }
2266 
2267 static PetscErrorCode PointQueueDequeue(PointQueue queue, PetscInt *p)
2268 {
2269   PetscFunctionBegin;
2270   if (!queue->num) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot dequeue from an empty queue");
2271   *p = queue->points[queue->front];
2272   queue->front = (queue->front + 1) % queue->size;
2273   --queue->num;
2274   PetscFunctionReturn(0);
2275 }
2276 
2277 #if 0
2278 static PetscErrorCode PointQueueFront(PointQueue queue, PetscInt *p)
2279 {
2280   PetscFunctionBegin;
2281   if (!queue->num) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot get the front of an empty queue");
2282   *p = queue->points[queue->front];
2283   PetscFunctionReturn(0);
2284 }
2285 
2286 static PetscErrorCode PointQueueBack(PointQueue queue, PetscInt *p)
2287 {
2288   PetscFunctionBegin;
2289   if (!queue->num) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot get the back of an empty queue");
2290   *p = queue->points[queue->back];
2291   PetscFunctionReturn(0);
2292 }
2293 #endif
2294 
2295 PETSC_STATIC_INLINE PetscBool PointQueueEmpty(PointQueue queue)
2296 {
2297   if (!queue->num) return PETSC_TRUE;
2298   return PETSC_FALSE;
2299 }
2300 
2301 static PetscErrorCode SBRGetEdgeLen_Private(DMPlexCellRefiner cr, PetscInt edge, PetscReal *len)
2302 {
2303   PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data;
2304   DM               dm  = cr->dm;
2305   PetscInt         off;
2306   PetscErrorCode   ierr;
2307 
2308   PetscFunctionBeginHot;
2309   ierr = PetscSectionGetOffset(sbr->secEdgeLen, edge, &off);CHKERRQ(ierr);
2310   if (sbr->edgeLen[off] <= 0.0) {
2311     DM                 cdm;
2312     Vec                coordsLocal;
2313     const PetscScalar *coords;
2314     const PetscInt    *cone;
2315     PetscScalar       *cA, *cB;
2316     PetscInt           coneSize, cdim;
2317 
2318     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
2319     ierr = DMPlexGetCone(dm, edge, &cone);CHKERRQ(ierr);
2320     ierr = DMPlexGetConeSize(dm, edge, &coneSize);CHKERRQ(ierr);
2321     if (coneSize != 2) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Edge %D cone size must be 2, not %D", edge, coneSize);
2322     ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
2323     ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
2324     ierr = VecGetArrayRead(coordsLocal, &coords);CHKERRQ(ierr);
2325     ierr = DMPlexPointLocalRead(cdm, cone[0], coords, &cA);CHKERRQ(ierr);
2326     ierr = DMPlexPointLocalRead(cdm, cone[1], coords, &cB);CHKERRQ(ierr);
2327     sbr->edgeLen[off] = DMPlex_DistD_Internal(cdim, cA, cB);
2328     ierr = VecRestoreArrayRead(coordsLocal, &coords);CHKERRQ(ierr);
2329   }
2330   *len = sbr->edgeLen[off];
2331   PetscFunctionReturn(0);
2332 }
2333 
2334 /* Mark local edges that should be split */
2335 /* TODO This will not work in 3D */
2336 static PetscErrorCode SBRSplitLocalEdges_Private(DMPlexCellRefiner cr, PointQueue queue)
2337 {
2338   PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data;
2339   DM               dm  = cr->dm;
2340   PetscErrorCode   ierr;
2341 
2342   PetscFunctionBegin;
2343   while (!PointQueueEmpty(queue)) {
2344     PetscInt        p = -1;
2345     const PetscInt *support;
2346     PetscInt        supportSize, s;
2347 
2348     ierr = PointQueueDequeue(queue, &p);CHKERRQ(ierr);
2349     ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr);
2350     ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
2351     for (s = 0; s < supportSize; ++s) {
2352       const PetscInt  cell = support[s];
2353       const PetscInt *cone;
2354       PetscInt        coneSize, c;
2355       PetscInt        cval, eval, maxedge;
2356       PetscReal       len, maxlen;
2357 
2358       ierr = DMLabelGetValue(sbr->splitPoints, cell, &cval);CHKERRQ(ierr);
2359       if (cval == 2) continue;
2360       ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr);
2361       ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr);
2362       ierr = SBRGetEdgeLen_Private(cr, cone[0], &maxlen);CHKERRQ(ierr);
2363       maxedge = cone[0];
2364       for (c = 1; c < coneSize; ++c) {
2365         ierr = SBRGetEdgeLen_Private(cr, cone[c], &len);CHKERRQ(ierr);
2366         if (len > maxlen) {maxlen = len; maxedge = cone[c];}
2367       }
2368       ierr = DMLabelGetValue(sbr->splitPoints, maxedge, &eval);CHKERRQ(ierr);
2369       if (eval != 1) {
2370         ierr = DMLabelSetValue(sbr->splitPoints, maxedge, 1);CHKERRQ(ierr);
2371         ierr = PointQueueEnqueue(queue, maxedge);CHKERRQ(ierr);
2372       }
2373       ierr = DMLabelSetValue(sbr->splitPoints, cell, 2);CHKERRQ(ierr);
2374     }
2375   }
2376   PetscFunctionReturn(0);
2377 }
2378 
2379 static PetscErrorCode SBRInitializeComm(DMPlexCellRefiner cr, PetscSF pointSF)
2380 {
2381   PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data;
2382   DMLabel          splitPoints = sbr->splitPoints;
2383   PetscInt        *splitArray  = sbr->splitArray;
2384   const PetscInt  *degree;
2385   const PetscInt  *points;
2386   PetscInt         Nl, l, pStart, pEnd, p, val;
2387   PetscErrorCode   ierr;
2388 
2389   PetscFunctionBegin;
2390   /* Add in leaves */
2391   ierr = PetscSFGetGraph(pointSF, NULL, &Nl, &points, NULL);CHKERRQ(ierr);
2392   for (l = 0; l < Nl; ++l) {
2393     ierr = DMLabelGetValue(splitPoints, points[l], &val);CHKERRQ(ierr);
2394     if (val > 0) splitArray[points[l]] = val;
2395   }
2396   /* Add in shared roots */
2397   ierr = PetscSFComputeDegreeBegin(pointSF, &degree);CHKERRQ(ierr);
2398   ierr = PetscSFComputeDegreeEnd(pointSF, &degree);CHKERRQ(ierr);
2399   ierr = DMPlexGetChart(cr->dm, &pStart, &pEnd);CHKERRQ(ierr);
2400   for (p = pStart; p < pEnd; ++p) {
2401     if (degree[p]) {
2402       ierr = DMLabelGetValue(splitPoints, p, &val);CHKERRQ(ierr);
2403       if (val > 0) splitArray[p] = val;
2404     }
2405   }
2406   PetscFunctionReturn(0);
2407 }
2408 
2409 static PetscErrorCode SBRFinalizeComm(DMPlexCellRefiner cr, PetscSF pointSF, PointQueue queue)
2410 {
2411   PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data;
2412   DMLabel          splitPoints = sbr->splitPoints;
2413   PetscInt        *splitArray  = sbr->splitArray;
2414   const PetscInt  *degree;
2415   const PetscInt  *points;
2416   PetscInt         Nl, l, pStart, pEnd, p, val;
2417   PetscErrorCode   ierr;
2418 
2419   PetscFunctionBegin;
2420   /* Read out leaves */
2421   ierr = PetscSFGetGraph(pointSF, NULL, &Nl, &points, NULL);CHKERRQ(ierr);
2422   for (l = 0; l < Nl; ++l) {
2423     const PetscInt p    = points[l];
2424     const PetscInt cval = splitArray[p];
2425 
2426     if (cval) {
2427       ierr = DMLabelGetValue(splitPoints, p, &val);CHKERRQ(ierr);
2428       if (val <= 0) {
2429         ierr = DMLabelSetValue(splitPoints, p, cval);CHKERRQ(ierr);
2430         ierr = PointQueueEnqueue(queue, p);CHKERRQ(ierr);
2431       }
2432     }
2433   }
2434   /* Read out shared roots */
2435   ierr = PetscSFComputeDegreeBegin(pointSF, &degree);CHKERRQ(ierr);
2436   ierr = PetscSFComputeDegreeEnd(pointSF, &degree);CHKERRQ(ierr);
2437   ierr = DMPlexGetChart(cr->dm, &pStart, &pEnd);CHKERRQ(ierr);
2438   for (p = pStart; p < pEnd; ++p) {
2439     if (degree[p]) {
2440       const PetscInt cval = splitArray[p];
2441 
2442       if (cval) {
2443         ierr = DMLabelGetValue(splitPoints, p, &val);CHKERRQ(ierr);
2444         if (val <= 0) {
2445           ierr = DMLabelSetValue(splitPoints, p, cval);CHKERRQ(ierr);
2446           ierr = PointQueueEnqueue(queue, p);CHKERRQ(ierr);
2447         }
2448       }
2449     }
2450   }
2451   PetscFunctionReturn(0);
2452 }
2453 
2454 static PetscErrorCode DMPlexCellRefinerSetUp_SBR(DMPlexCellRefiner cr)
2455 {
2456   PlexRefiner_SBR *sbr;
2457   PetscSF          pointSF;
2458   PointQueue       queue = NULL;
2459   IS               refineIS;
2460   const PetscInt  *refineCells;
2461   PetscMPIInt      size;
2462   PetscInt         pStart, pEnd, p, eStart, eEnd, e, edgeLenSize, Nc, c;
2463   PetscBool        empty;
2464   PetscErrorCode   ierr;
2465 
2466   PetscFunctionBegin;
2467   ierr = PetscCitationsRegister(SBRCitation, &SBRcite);CHKERRQ(ierr);
2468   ierr = PetscNew(&sbr);CHKERRQ(ierr);
2469   cr->data = sbr;
2470   ierr = DMLabelCreate(PETSC_COMM_SELF, "Split Points", &sbr->splitPoints);CHKERRQ(ierr);
2471   /* Create edge lengths */
2472   ierr = DMPlexGetDepthStratum(cr->dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
2473   ierr = PetscSectionCreate(PETSC_COMM_SELF, &sbr->secEdgeLen);CHKERRQ(ierr);
2474   ierr = PetscSectionSetChart(sbr->secEdgeLen, eStart, eEnd);CHKERRQ(ierr);
2475   for (e = eStart; e < eEnd; ++e) {
2476     ierr = PetscSectionSetDof(sbr->secEdgeLen, e, 1);CHKERRQ(ierr);
2477   }
2478   ierr = PetscSectionSetUp(sbr->secEdgeLen);CHKERRQ(ierr);
2479   ierr = PetscSectionGetStorageSize(sbr->secEdgeLen, &edgeLenSize);CHKERRQ(ierr);
2480   ierr = PetscCalloc1(edgeLenSize, &sbr->edgeLen);CHKERRQ(ierr);
2481   /* Add edges of cells that are marked for refinement to edge queue */
2482   if (!cr->adaptLabel) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_ARG_WRONGSTATE, "CellRefiner must have an adaptation label in order to use SBR algorithm");
2483   ierr = PointQueueCreate(1024, &queue);CHKERRQ(ierr);
2484   ierr = DMLabelGetStratumIS(cr->adaptLabel, DM_ADAPT_REFINE, &refineIS);CHKERRQ(ierr);
2485   ierr = DMLabelGetStratumSize(cr->adaptLabel, DM_ADAPT_REFINE, &Nc);CHKERRQ(ierr);
2486   if (refineIS) {ierr = ISGetIndices(refineIS, &refineCells);CHKERRQ(ierr);}
2487   for (c = 0; c < Nc; ++c) {
2488     PetscInt *closure = NULL;
2489     PetscInt  Ncl, cl;
2490 
2491     ierr = DMLabelSetValue(sbr->splitPoints, refineCells[c], 2);CHKERRQ(ierr);
2492     ierr = DMPlexGetTransitiveClosure(cr->dm, refineCells[c], PETSC_TRUE, &Ncl, &closure);CHKERRQ(ierr);
2493     for (cl = 0; cl < Ncl; cl += 2) {
2494       const PetscInt edge = closure[cl];
2495 
2496       if (edge >= eStart && edge < eEnd) {
2497         ierr = DMLabelSetValue(sbr->splitPoints, edge, 1);CHKERRQ(ierr);
2498         ierr = PointQueueEnqueue(queue, edge);CHKERRQ(ierr);
2499       }
2500     }
2501     ierr = DMPlexRestoreTransitiveClosure(cr->dm, refineCells[c], PETSC_TRUE, &Ncl, &closure);CHKERRQ(ierr);
2502   }
2503   if (refineIS) {ierr = ISRestoreIndices(refineIS, &refineCells);CHKERRQ(ierr);}
2504   ierr = ISDestroy(&refineIS);CHKERRQ(ierr);
2505   /* Setup communication */
2506   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) cr->dm), &size);CHKERRMPI(ierr);
2507   ierr = DMGetPointSF(cr->dm, &pointSF);CHKERRQ(ierr);
2508   if (size > 1) {
2509     PetscInt pStart, pEnd;
2510 
2511     ierr = DMPlexGetChart(cr->dm, &pStart, &pEnd);CHKERRQ(ierr);
2512     ierr = PetscCalloc1(pEnd-pStart, &sbr->splitArray);CHKERRQ(ierr);
2513   }
2514   /* While edge queue is not empty: */
2515   empty = PointQueueEmpty(queue);
2516   ierr = MPI_Allreduce(MPI_IN_PLACE, &empty, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject) cr->dm));CHKERRMPI(ierr);
2517   while (!empty) {
2518     ierr = SBRSplitLocalEdges_Private(cr, queue);CHKERRQ(ierr);
2519     /* Communicate marked edges
2520          An easy implementation is to allocate an array the size of the number of points. We put the splitPoints marks into the
2521          array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
2522 
2523          TODO: We could use in-place communication with a different SF
2524            We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
2525            already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
2526 
2527            In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
2528            values will have 1+0=1 and old values will have 1+1=2. Loop over these, resetting the values to 1, and adding any new
2529            edge to the queue.
2530     */
2531     if (size > 1) {
2532       ierr = SBRInitializeComm(cr, pointSF);CHKERRQ(ierr);
2533       ierr = PetscSFReduceBegin(pointSF, MPIU_INT, sbr->splitArray, sbr->splitArray, MPI_MAX);CHKERRQ(ierr);
2534       ierr = PetscSFReduceEnd(pointSF, MPIU_INT, sbr->splitArray, sbr->splitArray, MPI_MAX);CHKERRQ(ierr);
2535       ierr = PetscSFBcastBegin(pointSF, MPIU_INT, sbr->splitArray, sbr->splitArray,MPI_REPLACE);CHKERRQ(ierr);
2536       ierr = PetscSFBcastEnd(pointSF, MPIU_INT, sbr->splitArray, sbr->splitArray,MPI_REPLACE);CHKERRQ(ierr);
2537       ierr = SBRFinalizeComm(cr, pointSF, queue);CHKERRQ(ierr);
2538     }
2539     empty = PointQueueEmpty(queue);
2540     ierr = MPI_Allreduce(MPI_IN_PLACE, &empty, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject) cr->dm));CHKERRMPI(ierr);
2541   }
2542   ierr = PetscFree(sbr->splitArray);CHKERRQ(ierr);
2543   /* Calculate refineType for each cell */
2544   ierr = DMLabelCreate(PETSC_COMM_SELF, "Refine Type", &cr->refineType);CHKERRQ(ierr);
2545   ierr = DMPlexGetChart(cr->dm, &pStart, &pEnd);CHKERRQ(ierr);
2546   for (p = pStart; p < pEnd; ++p) {
2547     DMPolytopeType ct;
2548     PetscInt       val;
2549 
2550     ierr = DMPlexGetCellType(cr->dm, p, &ct);CHKERRQ(ierr);
2551     switch (ct) {
2552       case DM_POLYTOPE_POINT:
2553         ierr = DMLabelSetValue(cr->refineType, p, 0);CHKERRQ(ierr);break;
2554       case DM_POLYTOPE_SEGMENT:
2555         ierr = DMLabelGetValue(sbr->splitPoints, p, &val);CHKERRQ(ierr);
2556         if (val == 1) {ierr = DMLabelSetValue(cr->refineType, p, 2);CHKERRQ(ierr);}
2557         else          {ierr = DMLabelSetValue(cr->refineType, p, 1);CHKERRQ(ierr);}
2558         break;
2559       case DM_POLYTOPE_TRIANGLE:
2560         ierr = DMLabelGetValue(sbr->splitPoints, p, &val);CHKERRQ(ierr);
2561         if (val == 2) {
2562           const PetscInt *cone;
2563           PetscReal       lens[3];
2564           PetscInt        vals[3], i;
2565 
2566           ierr = DMPlexGetCone(cr->dm, p, &cone);CHKERRQ(ierr);
2567           for (i = 0; i < 3; ++i) {
2568             ierr = DMLabelGetValue(sbr->splitPoints, cone[i], &vals[i]);CHKERRQ(ierr);
2569             vals[i] = vals[i] < 0 ? 0 : vals[i];
2570             ierr = SBRGetEdgeLen_Private(cr, cone[i], &lens[i]);CHKERRQ(ierr);
2571           }
2572           if (vals[0] && vals[1] && vals[2]) {ierr = DMLabelSetValue(cr->refineType, p, 4);CHKERRQ(ierr);}
2573           else if (vals[0] && vals[1])       {ierr = DMLabelSetValue(cr->refineType, p, lens[0] > lens[1] ? 5 : 6);CHKERRQ(ierr);}
2574           else if (vals[1] && vals[2])       {ierr = DMLabelSetValue(cr->refineType, p, lens[1] > lens[2] ? 7 : 8);CHKERRQ(ierr);}
2575           else if (vals[2] && vals[0])       {ierr = DMLabelSetValue(cr->refineType, p, lens[2] > lens[0] ? 9: 10);CHKERRQ(ierr);}
2576           else if (vals[0])                  {ierr = DMLabelSetValue(cr->refineType, p, 11);CHKERRQ(ierr);}
2577           else if (vals[1])                  {ierr = DMLabelSetValue(cr->refineType, p, 12);CHKERRQ(ierr);}
2578           else if (vals[2])                  {ierr = DMLabelSetValue(cr->refineType, p, 13);CHKERRQ(ierr);}
2579           else SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cell %D does not fit any refinement type (%D, %D, %D)", p, vals[0], vals[1], vals[2]);
2580         } else {ierr = DMLabelSetValue(cr->refineType, p, 3);CHKERRQ(ierr);}
2581         break;
2582       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle points of type %s", DMPolytopeTypes[ct]);
2583     }
2584     ierr = DMLabelGetValue(sbr->splitPoints, p, &val);CHKERRQ(ierr);
2585   }
2586   /* Cleanup */
2587   ierr = PointQueueDestroy(&queue);CHKERRQ(ierr);
2588   PetscFunctionReturn(0);
2589 }
2590 
2591 static PetscErrorCode DMPlexCellRefinerDestroy_SBR(DMPlexCellRefiner cr)
2592 {
2593   PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data;
2594   PetscErrorCode   ierr;
2595 
2596   PetscFunctionBegin;
2597   ierr = PetscFree(sbr->edgeLen);CHKERRQ(ierr);
2598   ierr = PetscSectionDestroy(&sbr->secEdgeLen);CHKERRQ(ierr);
2599   ierr = DMLabelDestroy(&sbr->splitPoints);CHKERRQ(ierr);
2600   ierr = PetscFree(cr->data);CHKERRQ(ierr);
2601   PetscFunctionReturn(0);
2602 }
2603 
2604 static PetscErrorCode DMPlexCellRefinerRefine_SBR(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
2605 {
2606   /* Add 1 edge inside this triangle, making 2 new triangles.
2607    2
2608    |\
2609    | \
2610    |  \
2611    |   \
2612    |    1
2613    |     \
2614    |  B   \
2615    2       1
2616    |      / \
2617    | ____/   0
2618    |/    A    \
2619    0-----0-----1
2620   */
2621   static DMPolytopeType triT10[]  = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE};
2622   static PetscInt       triS10[]  = {1, 2};
2623   static PetscInt       triC10[]  = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
2624                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0,
2625                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    0};
2626   static PetscInt       triO10[]  = {0, 0,
2627                                      0,  0, -2,
2628                                      0,  0,  0};
2629   /* Add 1 edge inside this triangle, making 2 new triangles.
2630    2
2631    |\
2632    | \
2633    |  \
2634    0   \
2635    |    \
2636    |     \
2637    |      \
2638    2   A   1
2639    |\       \
2640    1 ---\    \
2641    |  B  ----\\
2642    0-----0-----1
2643   */
2644   static PetscInt       triC11[]  = {DM_POLYTOPE_POINT, 2, 1, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0,
2645                                      DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    0,
2646                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0};
2647   static PetscInt       triO11[]  = {0, 0,
2648                                      0,  0, -2,
2649                                      0,  0,  0};
2650   /* Add 1 edge inside this triangle, making 2 new triangles.
2651    2
2652    |\
2653    |\\
2654    || \
2655    | \ \
2656    |  | \
2657    |  |  \
2658    |  |   \
2659    2   \   1
2660    |  A |   \
2661    |    |  B \
2662    |     \    \
2663    0-----0-----1
2664   */
2665   static PetscInt       triC12[]  = {DM_POLYTOPE_POINT, 2, 2, 0, 0, DM_POLYTOPE_POINT, 1, 0, 0,
2666                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0,
2667                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0};
2668   static PetscInt       triO12[]  = {0, 0,
2669                                      0,  0, -2,
2670                                      0,  0,  0};
2671   /* Add 2 edges inside this triangle, making 3 new triangles.
2672    2
2673    |\
2674    | \
2675    |  \
2676    0   \
2677    |    1
2678    |     \
2679    |  B   \
2680    2-------1
2681    |   C  / \
2682    1 ____/   0
2683    |/    A    \
2684    0-----0-----1
2685   */
2686   static DMPolytopeType triT20[]  = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE};
2687   static PetscInt       triS20[]  = {2, 3};
2688   static PetscInt       triC20[]  = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
2689                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 2, 0,
2690                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0,
2691                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    1,
2692                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1};
2693   static PetscInt       triO20[]  = {0, 0,
2694                                      0, 0,
2695                                      0,  0, -2,
2696                                      0,  0, -2,
2697                                      0,  0,  0};
2698   /* Add 1 edge inside this triangle, making 2 new triangles.
2699    2
2700    |\
2701    | \
2702    |  \
2703    0   \
2704    |    1
2705    |     \
2706    |  B   \
2707    2       1
2708    |      /|\
2709    1 ____/ / 0
2710    |/ A   / C \
2711    0-----0-----1
2712   */
2713   static PetscInt       triC21[]  = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
2714                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 0, 0,
2715                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
2716                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    0,
2717                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1};
2718   static PetscInt       triO21[]  = {0, 0,
2719                                      0, 0,
2720                                      0, -2, -2,
2721                                      0,  0,  0,
2722                                      0,  0,  0};
2723   /* Add 2 edges inside this triangle, making 3 new triangles.
2724    2
2725    |\
2726    | \
2727    |  \
2728    0   \
2729    |    \
2730    |     \
2731    |      \
2732    2   A   1
2733    |\       \
2734    1 ---\    \
2735    |B \_C----\\
2736    0-----0-----1
2737   */
2738   static PetscInt       triC22[]  = {DM_POLYTOPE_POINT, 2, 1, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0,
2739                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 0, 0,
2740                                      DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    0,
2741                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    1,
2742                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1};
2743   static PetscInt       triO22[]  = {0, 0,
2744                                      0, 0,
2745                                      0,  0, -2,
2746                                      0,  0, -2,
2747                                      0,  0,  0};
2748   /* Add 1 edge inside this triangle, making 2 new triangles.
2749    2
2750    |\
2751    | \
2752    |  \
2753    0   \
2754    |    \
2755    |  C  \
2756    |      \
2757    2-------1
2758    |\     A \
2759    1 ---\    \
2760    |  B  ----\\
2761    0-----0-----1
2762   */
2763   static PetscInt       triC23[]  = {DM_POLYTOPE_POINT, 2, 1, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0,
2764                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 1, 0,
2765                                      DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
2766                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0,
2767                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    1};
2768   static PetscInt       triO23[]  = {0, 0,
2769                                      0, 0,
2770                                      0, -2, -2,
2771                                      0,  0,  0,
2772                                      0,  0,  0};
2773   /* Add 2 edges inside this triangle, making 3 new triangles.
2774    2
2775    |\
2776    |\\
2777    || \
2778    | \ \
2779    |  | \
2780    |  |  \
2781    |  |   \
2782    2   \ C 1
2783    |  A | / \
2784    |    | |B \
2785    |     \/   \
2786    0-----0-----1
2787   */
2788   static PetscInt       triC24[]  = {DM_POLYTOPE_POINT, 2, 2, 0, 0, DM_POLYTOPE_POINT, 1, 0, 0,
2789                                      DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
2790                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0,
2791                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1,
2792                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1};
2793   static PetscInt       triO24[]  = {0, 0,
2794                                      0, 0,
2795                                      0,  0, -2,
2796                                      0,  0, -2,
2797                                      0,  0,  0};
2798   /* Add 1 edge inside this triangle, making 2 new triangles.
2799    2
2800    |\
2801    |\\
2802    || \
2803    | \ \
2804    |  | \
2805    |  |  \
2806    |  |   \
2807    2 A \   1
2808    |\   |   \
2809    | \__|  B \
2810    | C  \\    \
2811    0-----0-----1
2812   */
2813   static PetscInt       triC25[]  = {DM_POLYTOPE_POINT, 2, 2, 0, 0, DM_POLYTOPE_POINT, 1, 0, 0,
2814                                      DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0,
2815                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
2816                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0,
2817                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    1};
2818   static PetscInt       triO25[]  = {0, 0,
2819                                      0, 0,
2820                                      0, -2, -2,
2821                                      0,  0,  0,
2822                                      0,  0,  0};
2823   DMLabel        rtype = cr->refineType;
2824   PetscInt       val;
2825   PetscErrorCode ierr;
2826 
2827 
2828   PetscFunctionBeginHot;
2829   if (p < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point argument is invalid");
2830   ierr = DMLabelGetValue(rtype, p, &val);CHKERRQ(ierr);
2831   if (rt) *rt = val;
2832   switch (source) {
2833     case DM_POLYTOPE_POINT:
2834     case DM_POLYTOPE_POINT_PRISM_TENSOR:
2835     case DM_POLYTOPE_QUADRILATERAL:
2836     case DM_POLYTOPE_SEG_PRISM_TENSOR:
2837     case DM_POLYTOPE_TETRAHEDRON:
2838     case DM_POLYTOPE_HEXAHEDRON:
2839     case DM_POLYTOPE_TRI_PRISM:
2840     case DM_POLYTOPE_TRI_PRISM_TENSOR:
2841     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
2842     case DM_POLYTOPE_PYRAMID:
2843       ierr = DMPlexCellRefinerRefine_None(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr);
2844       break;
2845     case DM_POLYTOPE_SEGMENT:
2846       if (val == 1) {ierr = DMPlexCellRefinerRefine_None(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr);}
2847       else          {ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr);}
2848       break;
2849     case DM_POLYTOPE_TRIANGLE:
2850       switch (val) {
2851         case 12: *Nt = 2; *target = triT10; *size = triS10; *cone = triC10; *ornt = triO10; break;
2852         case 13: *Nt = 2; *target = triT10; *size = triS10; *cone = triC11; *ornt = triO11; break;
2853         case 11: *Nt = 2; *target = triT10; *size = triS10; *cone = triC12; *ornt = triO12; break;
2854         case  5: *Nt = 2; *target = triT20; *size = triS20; *cone = triC24; *ornt = triO24; break;
2855         case  6: *Nt = 2; *target = triT20; *size = triS20; *cone = triC21; *ornt = triO21; break;
2856         case  7: *Nt = 2; *target = triT20; *size = triS20; *cone = triC20; *ornt = triO20; break;
2857         case  8: *Nt = 2; *target = triT20; *size = triS20; *cone = triC23; *ornt = triO23; break;
2858         case  9: *Nt = 2; *target = triT20; *size = triS20; *cone = triC22; *ornt = triO22; break;
2859         case 10: *Nt = 2; *target = triT20; *size = triS20; *cone = triC25; *ornt = triO25; break;
2860         case  4: ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr); break;
2861         default: ierr = DMPlexCellRefinerRefine_None(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr);
2862       }
2863       break;
2864     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
2865   }
2866   PetscFunctionReturn(0);
2867 }
2868 
2869 static PetscErrorCode DMPlexCellRefinerMapSubcells_SBR(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
2870 {
2871   /* We shift any input orientation in order to make it non-negative
2872        The orientation array o[po][o] gives the orientation the new replica rnew has to have in order to reproduce the face sequence from (r, o)
2873        The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po
2874        Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po
2875   */
2876   PetscInt         rt;
2877   PetscErrorCode   ierr;
2878 
2879   PetscFunctionBeginHot;
2880   ierr = DMLabelGetValue(cr->refineType, pp, &rt);CHKERRQ(ierr);
2881   *rnew = r;
2882   *onew = o;
2883   switch (rt) {
2884     case 5:
2885     case 6:
2886     case 7:
2887     case 8:
2888     case 9:
2889     case 10:
2890       switch (ct) {
2891         case DM_POLYTOPE_SEGMENT:
2892           break;
2893         case DM_POLYTOPE_TRIANGLE:
2894           break;
2895         default: break;
2896       }
2897       break;
2898     case 11:
2899     case 12:
2900     case 13:
2901       switch (ct) {
2902         case DM_POLYTOPE_SEGMENT:
2903           break;
2904         case DM_POLYTOPE_TRIANGLE:
2905           *onew = po < 0 ? -(o+1)  : o;
2906           *rnew = po < 0 ? (r+1)%2 : r;
2907           break;
2908         default: break;
2909       }
2910       break;
2911     case 2:
2912     case 4:
2913       ierr = DMPlexCellRefinerMapSubcells_Regular(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
2914       break;
2915     default: ierr = DMPlexCellRefinerMapSubcells_None(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
2916   }
2917   PetscFunctionReturn(0);
2918 }
2919 
2920 static PetscErrorCode CellRefinerCreateOffset_Internal(DMPlexCellRefiner cr, PetscInt ctOrder[], PetscInt ctStart[], PetscInt **offset)
2921 {
2922   PetscInt       c, cN, *off;
2923   PetscErrorCode ierr;
2924 
2925   PetscFunctionBegin;
2926   if (cr->refineType) {
2927     IS              rtIS;
2928     const PetscInt *reftypes;
2929     PetscInt        Nrt, r;
2930 
2931     ierr = DMLabelGetNumValues(cr->refineType, &Nrt);CHKERRQ(ierr);
2932     ierr = DMLabelGetValueIS(cr->refineType, &rtIS);CHKERRQ(ierr);
2933     ierr = ISGetIndices(rtIS, &reftypes);CHKERRQ(ierr);
2934     ierr = PetscCalloc1(Nrt*DM_NUM_POLYTOPES, &off);CHKERRQ(ierr);
2935     for (r = 0; r < Nrt; ++r) {
2936       const PetscInt  rt = reftypes[r];
2937       IS              rtIS;
2938       const PetscInt *points;
2939       DMPolytopeType  ct;
2940       PetscInt        p;
2941 
2942       ierr = DMLabelGetStratumIS(cr->refineType, rt, &rtIS);CHKERRQ(ierr);
2943       ierr = ISGetIndices(rtIS, &points);CHKERRQ(ierr);
2944       p    = points[0];
2945       ierr = ISRestoreIndices(rtIS, &points);CHKERRQ(ierr);
2946       ierr = ISDestroy(&rtIS);CHKERRQ(ierr);
2947       ierr = DMPlexGetCellType(cr->dm, p, &ct);CHKERRQ(ierr);
2948       for (cN = DM_POLYTOPE_POINT; cN < DM_NUM_POLYTOPES; ++cN) {
2949         const DMPolytopeType ctNew = (DMPolytopeType) cN;
2950         DMPolytopeType      *rct;
2951         PetscInt            *rsize, *cone, *ornt;
2952         PetscInt             Nct, n, s;
2953 
2954         if (DMPolytopeTypeGetDim(ct) < 0 || DMPolytopeTypeGetDim(ctNew) < 0) {off[r*DM_NUM_POLYTOPES+ctNew] = -1; break;}
2955         off[r*DM_NUM_POLYTOPES+ctNew] = 0;
2956         for (s = 0; s <= r; ++s) {
2957           const PetscInt st = reftypes[s];
2958           DMPolytopeType sct;
2959           PetscInt       q, qrt;
2960 
2961           ierr = DMLabelGetStratumIS(cr->refineType, st, &rtIS);CHKERRQ(ierr);
2962           ierr = ISGetIndices(rtIS, &points);CHKERRQ(ierr);
2963           q    = points[0];
2964           ierr = ISRestoreIndices(rtIS, &points);CHKERRQ(ierr);
2965           ierr = ISDestroy(&rtIS);CHKERRQ(ierr);
2966           ierr = DMPlexGetCellType(cr->dm, q, &sct);CHKERRQ(ierr);
2967           ierr = DMPlexCellRefinerRefine(cr, sct, q, &qrt, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
2968           if (st != qrt) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Refine type %D of point %D does not match predicted type %D", qrt, q, st);
2969           if (st == rt) {
2970             for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) break;
2971             if (n == Nct) off[r*DM_NUM_POLYTOPES+ctNew] = -1;
2972             break;
2973           }
2974           for (n = 0; n < Nct; ++n) {
2975             if (rct[n] == ctNew) {
2976               PetscInt sn;
2977 
2978               ierr = DMLabelGetStratumSize(cr->refineType, st, &sn);CHKERRQ(ierr);
2979               off[r*DM_NUM_POLYTOPES+ctNew] += sn * rsize[n];
2980             }
2981           }
2982         }
2983       }
2984     }
2985 #if 0
2986     {
2987       PetscInt cols = 8;
2988       PetscInt f, g;
2989       ierr = PetscPrintf(PETSC_COMM_SELF, "Offsets\n");CHKERRQ(ierr);
2990       ierr = PetscPrintf(PETSC_COMM_SELF, "     ");CHKERRQ(ierr);
2991       for (g = 0; g < cols; ++g) {
2992         ierr = PetscPrintf(PETSC_COMM_SELF, " % 14s", DMPolytopeTypes[g]);CHKERRQ(ierr);
2993       }
2994       ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
2995       for (f = 0; f < Nrt; ++f) {
2996         ierr = PetscPrintf(PETSC_COMM_SELF, "%2d  |", reftypes[f]);CHKERRQ(ierr);
2997         for (g = 0; g < cols; ++g) {
2998           ierr = PetscPrintf(PETSC_COMM_SELF, " % 14d", PetscRealPart(off[f*DM_NUM_POLYTOPES+g]));CHKERRQ(ierr);
2999         }
3000         ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr);
3001       }
3002     }
3003 #endif
3004     ierr = ISRestoreIndices(rtIS, &reftypes);CHKERRQ(ierr);
3005     ierr = ISDestroy(&rtIS);CHKERRQ(ierr);
3006   } else {
3007     ierr = PetscCalloc1(DM_NUM_POLYTOPES*DM_NUM_POLYTOPES, &off);CHKERRQ(ierr);
3008     for (c = DM_POLYTOPE_POINT; c < DM_NUM_POLYTOPES; ++c) {
3009       const DMPolytopeType ct = (DMPolytopeType) c;
3010       for (cN = DM_POLYTOPE_POINT; cN < DM_NUM_POLYTOPES; ++cN) {
3011         const DMPolytopeType ctNew = (DMPolytopeType) cN;
3012         DMPolytopeType      *rct;
3013         PetscInt            *rsize, *cone, *ornt;
3014         PetscInt             Nct, n, i;
3015 
3016         if (DMPolytopeTypeGetDim(ct) < 0 || DMPolytopeTypeGetDim(ctNew) < 0) {off[ct*DM_NUM_POLYTOPES+ctNew] = -1; break;}
3017         off[ct*DM_NUM_POLYTOPES+ctNew] = 0;
3018         for (i = DM_POLYTOPE_POINT; i < DM_NUM_POLYTOPES; ++i) {
3019           const DMPolytopeType ict  = (DMPolytopeType) ctOrder[i];
3020           const DMPolytopeType ictn = (DMPolytopeType) ctOrder[i+1];
3021 
3022           ierr = DMPlexCellRefinerRefine(cr, ict, PETSC_DETERMINE, NULL, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
3023           if (ict == ct) {
3024             for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) break;
3025             if (n == Nct) off[ct*DM_NUM_POLYTOPES+ctNew] = -1;
3026             break;
3027           }
3028           for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) off[ct*DM_NUM_POLYTOPES+ctNew] += (ctStart[ictn]-ctStart[ict]) * rsize[n];
3029         }
3030       }
3031     }
3032   }
3033   *offset = off;
3034   PetscFunctionReturn(0);
3035 }
3036 
3037 static PetscErrorCode DMPlexCellRefinerSetStarts(DMPlexCellRefiner cr, const PetscInt ctStart[], const PetscInt ctStartNew[])
3038 {
3039   const PetscInt ctSize = DM_NUM_POLYTOPES+1;
3040   PetscErrorCode ierr;
3041 
3042   PetscFunctionBegin;
3043   if (cr->setupcalled) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_ARG_WRONGSTATE, "Must call this function before DMPlexCellRefinerSetUp()");
3044   ierr = PetscCalloc2(ctSize, &cr->ctStart, ctSize, &cr->ctStartNew);CHKERRQ(ierr);
3045   ierr = PetscArraycpy(cr->ctStart,    ctStart,    ctSize);CHKERRQ(ierr);
3046   ierr = PetscArraycpy(cr->ctStartNew, ctStartNew, ctSize);CHKERRQ(ierr);
3047   PetscFunctionReturn(0);
3048 }
3049 
3050 /* Construct cell type order since we must loop over cell types in depth order */
3051 PetscErrorCode DMPlexCreateCellTypeOrder_Internal(DMPolytopeType ctCell, PetscInt *ctOrder[], PetscInt *ctOrderInv[])
3052 {
3053   PetscInt      *ctO, *ctOInv;
3054   PetscInt       c, d, off = 0;
3055   PetscErrorCode ierr;
3056 
3057   PetscFunctionBegin;
3058   ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctO, DM_NUM_POLYTOPES+1, &ctOInv);CHKERRQ(ierr);
3059   for (d = 3; d >= DMPolytopeTypeGetDim(ctCell); --d) {
3060     for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
3061       if (DMPolytopeTypeGetDim((DMPolytopeType) c) != d) continue;
3062       ctO[off++] = c;
3063     }
3064   }
3065   if (DMPolytopeTypeGetDim(ctCell) != 0) {
3066     for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
3067       if (DMPolytopeTypeGetDim((DMPolytopeType) c) != 0) continue;
3068       ctO[off++] = c;
3069     }
3070   }
3071   for (d = DMPolytopeTypeGetDim(ctCell)-1; d > 0; --d) {
3072     for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
3073       if (DMPolytopeTypeGetDim((DMPolytopeType) c) != d) continue;
3074       ctO[off++] = c;
3075     }
3076   }
3077   for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
3078     if (DMPolytopeTypeGetDim((DMPolytopeType) c) >= 0) continue;
3079     ctO[off++] = c;
3080   }
3081   if (off != DM_NUM_POLYTOPES+1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid offset %D for cell type order", off);
3082   for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
3083     ctOInv[ctO[c]] = c;
3084   }
3085   *ctOrder    = ctO;
3086   *ctOrderInv = ctOInv;
3087   PetscFunctionReturn(0);
3088 }
3089 
3090 PetscErrorCode DMPlexCellRefinerSetUp(DMPlexCellRefiner cr)
3091 {
3092   DM             dm = cr->dm;
3093   DMPolytopeType ctCell;
3094   PetscInt       pStart, pEnd, p, c;
3095   PetscErrorCode ierr;
3096 
3097   PetscFunctionBegin;
3098   PetscValidHeader(cr, 1);
3099   if (cr->setupcalled) PetscFunctionReturn(0);
3100   if (cr->ops->setup) {
3101     ierr = (*cr->ops->setup)(cr);CHKERRQ(ierr);
3102   }
3103   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3104   if (pEnd > pStart) {
3105     ierr = DMPlexGetCellType(dm, 0, &ctCell);CHKERRQ(ierr);
3106   } else {
3107     PetscInt dim;
3108     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
3109     switch (dim) {
3110     case 0: ctCell = DM_POLYTOPE_POINT;break;
3111     case 1: ctCell = DM_POLYTOPE_SEGMENT;break;
3112     case 2: ctCell = DM_POLYTOPE_TRIANGLE;break;
3113     case 3: ctCell = DM_POLYTOPE_TETRAHEDRON;break;
3114     default: ctCell = DM_POLYTOPE_UNKNOWN;
3115     }
3116   }
3117   ierr = DMPlexCreateCellTypeOrder_Internal(ctCell, &cr->ctOrder, &cr->ctOrderInv);CHKERRQ(ierr);
3118   /* Construct sizes and offsets for each cell type */
3119   if (!cr->ctStart) {
3120     PetscInt *ctS, *ctSN, *ctC, *ctCN;
3121 
3122     ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctS, DM_NUM_POLYTOPES+1, &ctSN);CHKERRQ(ierr);
3123     ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctC, DM_NUM_POLYTOPES+1, &ctCN);CHKERRQ(ierr);
3124     for (p = pStart; p < pEnd; ++p) {
3125       DMPolytopeType  ct;
3126       DMPolytopeType *rct;
3127       PetscInt       *rsize, *cone, *ornt;
3128       PetscInt        Nct, n;
3129 
3130       ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
3131       if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell type for point %D", p);
3132       ++ctC[ct];
3133       ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
3134       for (n = 0; n < Nct; ++n) ctCN[rct[n]] += rsize[n];
3135     }
3136     for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
3137       const PetscInt ct  = cr->ctOrder[c];
3138       const PetscInt ctn = cr->ctOrder[c+1];
3139 
3140       ctS[ctn]  = ctS[ct]  + ctC[ct];
3141       ctSN[ctn] = ctSN[ct] + ctCN[ct];
3142     }
3143     ierr = PetscFree2(ctC, ctCN);CHKERRQ(ierr);
3144     cr->ctStart    = ctS;
3145     cr->ctStartNew = ctSN;
3146   }
3147   ierr = CellRefinerCreateOffset_Internal(cr, cr->ctOrder, cr->ctStart, &cr->offset);CHKERRQ(ierr);
3148   cr->setupcalled = PETSC_TRUE;
3149   PetscFunctionReturn(0);
3150 }
3151 
3152 static PetscErrorCode DMPlexCellRefinerView_Ascii(DMPlexCellRefiner cr, PetscViewer v)
3153 {
3154   PetscErrorCode ierr;
3155 
3156   PetscFunctionBegin;
3157   ierr = PetscViewerASCIIPrintf(v, "Cell Refiner: %s\n", DMPlexCellRefinerTypes[cr->type]);CHKERRQ(ierr);
3158   PetscFunctionReturn(0);
3159 }
3160 
3161 /*
3162   DMPlexCellRefinerView - Views a DMPlexCellRefiner object
3163 
3164   Collective on cr
3165 
3166   Input Parameters:
3167 + cr     - The DMPlexCellRefiner object
3168 - viewer - The PetscViewer object
3169 
3170   Level: beginner
3171 
3172 .seealso: DMPlexCellRefinerCreate()
3173 */
3174 static PetscErrorCode DMPlexCellRefinerView(DMPlexCellRefiner cr, PetscViewer viewer)
3175 {
3176   PetscBool      iascii;
3177   PetscErrorCode ierr;
3178 
3179   PetscFunctionBegin;
3180   PetscValidHeader(cr, 1);
3181   if (viewer) PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3182   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) cr), &viewer);CHKERRQ(ierr);}
3183   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
3184   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
3185   if (iascii) {ierr = DMPlexCellRefinerView_Ascii(cr, viewer);CHKERRQ(ierr);}
3186   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
3187   PetscFunctionReturn(0);
3188 }
3189 
3190 PetscErrorCode DMPlexCellRefinerDestroy(DMPlexCellRefiner *cr)
3191 {
3192   PetscInt       c;
3193   PetscErrorCode ierr;
3194 
3195   PetscFunctionBegin;
3196   if (!*cr) PetscFunctionReturn(0);
3197   PetscValidHeaderSpecific(*cr, DM_CLASSID, 1);
3198   if ((*cr)->ops->destroy) {
3199     ierr = ((*cr)->ops->destroy)(*cr);CHKERRQ(ierr);
3200   }
3201   ierr = PetscObjectDereference((PetscObject) (*cr)->dm);CHKERRQ(ierr);
3202   ierr = DMLabelDestroy(&(*cr)->refineType);CHKERRQ(ierr);
3203   ierr = PetscFree2((*cr)->ctOrder, (*cr)->ctOrderInv);CHKERRQ(ierr);
3204   ierr = PetscFree2((*cr)->ctStart, (*cr)->ctStartNew);CHKERRQ(ierr);
3205   ierr = PetscFree((*cr)->offset);CHKERRQ(ierr);
3206   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
3207     ierr = PetscFEDestroy(&(*cr)->coordFE[c]);CHKERRQ(ierr);
3208     ierr = PetscFEGeomDestroy(&(*cr)->refGeom[c]);CHKERRQ(ierr);
3209   }
3210   ierr = PetscFree2((*cr)->coordFE, (*cr)->refGeom);CHKERRQ(ierr);
3211   ierr = PetscHeaderDestroy(cr);CHKERRQ(ierr);
3212   PetscFunctionReturn(0);
3213 }
3214 
3215 PetscErrorCode DMPlexCellRefinerCreate(DM dm, DMPlexCellRefiner *cr)
3216 {
3217   DMPlexCellRefiner tmp;
3218   PetscErrorCode    ierr;
3219 
3220   PetscFunctionBegin;
3221   PetscValidPointer(cr, 2);
3222   *cr  = NULL;
3223   ierr = PetscHeaderCreate(tmp, DM_CLASSID, "DMPlexCellRefiner", "Cell Refiner", "DMPlexCellRefiner", PETSC_COMM_SELF, DMPlexCellRefinerDestroy, DMPlexCellRefinerView);CHKERRQ(ierr);
3224   tmp->setupcalled = PETSC_FALSE;
3225 
3226   tmp->dm = dm;
3227   ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
3228   ierr = DMPlexGetCellRefinerType(dm, &tmp->type);CHKERRQ(ierr);
3229   switch (tmp->type) {
3230   case DM_REFINER_REGULAR:
3231     tmp->ops->refine                  = DMPlexCellRefinerRefine_Regular;
3232     tmp->ops->mapsubcells             = DMPlexCellRefinerMapSubcells_Regular;
3233     tmp->ops->getcellvertices         = DMPlexCellRefinerGetCellVertices_Regular;
3234     tmp->ops->getsubcellvertices      = DMPlexCellRefinerGetSubcellVertices_Regular;
3235     tmp->ops->mapcoords               = DMPlexCellRefinerMapCoordinates_Barycenter;
3236     tmp->ops->getaffinetransforms     = DMPlexCellRefinerGetAffineTransforms_Regular;
3237     tmp->ops->getaffinefacetransforms = DMPlexCellRefinerGetAffineFaceTransforms_Regular;
3238     break;
3239   case DM_REFINER_TO_BOX:
3240     tmp->ops->refine             = DMPlexCellRefinerRefine_ToBox;
3241     tmp->ops->mapsubcells        = DMPlexCellRefinerMapSubcells_ToBox;
3242     tmp->ops->getcellvertices    = DMPlexCellRefinerGetCellVertices_ToBox;
3243     tmp->ops->getsubcellvertices = DMPlexCellRefinerGetSubcellVertices_ToBox;
3244     tmp->ops->mapcoords          = DMPlexCellRefinerMapCoordinates_Barycenter;
3245     break;
3246   case DM_REFINER_TO_SIMPLEX:
3247     tmp->ops->refine      = DMPlexCellRefinerRefine_ToSimplex;
3248     tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_ToSimplex;
3249     tmp->ops->mapcoords   = DMPlexCellRefinerMapCoordinates_Barycenter;
3250     break;
3251   case DM_REFINER_ALFELD2D:
3252     tmp->ops->refine      = DMPlexCellRefinerRefine_Alfeld2D;
3253     tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_None;
3254     tmp->ops->mapcoords   = DMPlexCellRefinerMapCoordinates_Barycenter;
3255     break;
3256   case DM_REFINER_ALFELD3D:
3257     tmp->ops->refine      = DMPlexCellRefinerRefine_Alfeld3D;
3258     tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_None;
3259     tmp->ops->mapcoords   = DMPlexCellRefinerMapCoordinates_Barycenter;
3260     break;
3261   case DM_REFINER_BOUNDARYLAYER:
3262     tmp->ops->setup       = DMPlexCellRefinerSetUp_BL;
3263     tmp->ops->destroy     = DMPlexCellRefinerDestroy_BL;
3264     tmp->ops->refine      = DMPlexCellRefinerRefine_BL;
3265     tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_BL;
3266     tmp->ops->mapcoords   = DMPlexCellRefinerMapCoordinates_BL;
3267     break;
3268   case DM_REFINER_SBR:
3269     tmp->ops->setup       = DMPlexCellRefinerSetUp_SBR;
3270     tmp->ops->destroy     = DMPlexCellRefinerDestroy_SBR;
3271     tmp->ops->refine      = DMPlexCellRefinerRefine_SBR;
3272     tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_SBR;
3273     tmp->ops->mapcoords   = DMPlexCellRefinerMapCoordinates_Barycenter;
3274     break;
3275   default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Invalid cell refiner type %s", DMPlexCellRefinerTypes[tmp->type]);
3276   }
3277   ierr = PetscCalloc2(DM_NUM_POLYTOPES, &tmp->coordFE, DM_NUM_POLYTOPES, &tmp->refGeom);CHKERRQ(ierr);
3278   *cr = tmp;
3279   PetscFunctionReturn(0);
3280 }
3281 
3282 /*@
3283   DMPlexCellRefinerGetAffineTransforms - Gets the affine map from the reference cell to each subcell
3284 
3285   Input Parameters:
3286 + cr - The DMPlexCellRefiner object
3287 - ct - The cell type
3288 
3289   Output Parameters:
3290 + Nc   - The number of subcells produced from this cell type
3291 . v0   - The translation of the first vertex for each subcell
3292 . J    - The Jacobian for each subcell (map from reference cell to subcell)
3293 - invJ - The inverse Jacobian for each subcell
3294 
3295   Level: developer
3296 
3297 .seealso: DMPlexCellRefinerGetAffineFaceTransforms(), Create()
3298 @*/
3299 PetscErrorCode DMPlexCellRefinerGetAffineTransforms(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nc, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[])
3300 {
3301   PetscErrorCode ierr;
3302 
3303   PetscFunctionBegin;
3304   if (!cr->ops->getaffinetransforms) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_SUP, "No support for affine transforms from this refiner");
3305   ierr = (*cr->ops->getaffinetransforms)(cr, ct, Nc, v0, J, invJ);CHKERRQ(ierr);
3306   PetscFunctionReturn(0);
3307 }
3308 
3309 /*@
3310   DMPlexCellRefinerGetAffineFaceTransforms - Gets the affine map from the reference face cell to each face in the given cell
3311 
3312   Input Parameters:
3313 + cr - The DMPlexCellRefiner object
3314 - ct - The cell type
3315 
3316   Output Parameters:
3317 + Nf   - The number of faces for this cell type
3318 . v0   - The translation of the first vertex for each face
3319 . J    - The Jacobian for each face (map from original cell to subcell)
3320 . invJ - The inverse Jacobian for each face
3321 - detJ - The determinant of the Jacobian for each face
3322 
3323   Note: The Jacobian and inverse Jacboian will be rectangular, and the inverse is really a generalized inverse.
3324 
3325   Level: developer
3326 
3327 .seealso: DMPlexCellRefinerGetAffineTransforms(), Create()
3328 @*/
3329 PetscErrorCode DMPlexCellRefinerGetAffineFaceTransforms(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nf, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[], PetscReal *detJ[])
3330 {
3331   PetscErrorCode ierr;
3332 
3333   PetscFunctionBegin;
3334   if (!cr->ops->getaffinefacetransforms) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_SUP, "No support for affine face transforms from this refiner");
3335   ierr = (*cr->ops->getaffinefacetransforms)(cr, ct, Nf, v0, J, invJ, detJ);CHKERRQ(ierr);
3336   PetscFunctionReturn(0);
3337 }
3338 
3339 /* Numbering regularly refined meshes
3340 
3341    We want the numbering of the new mesh to respect the same depth stratification as the old mesh. We first compute
3342    the number of new points at each depth. This means that offsets for each depth can be computed, making no assumptions
3343    about the order of different cell types.
3344 
3345    However, when we want to order different depth strata, it will be very useful to make assumptions about contiguous
3346    numbering of different cell types, especially if we want to compute new numberings without communication. Therefore, we
3347    will require that cells are numbering contiguously for each cell type, and that those blocks come in the same order as
3348    the cell type enumeration within a given depth stratum.
3349 
3350    Thus, at each depth, each cell type will add a certain number of points at that depth. To get the new point number, we
3351    start at the new depth offset, run through all prior cell types incrementing by the total addition from that type, then
3352    offset by the old cell type number and replica number for the insertion.
3353 */
3354 
3355 static PetscErrorCode DMPlexCellRefinerGetReducedPointNumber(DMPlexCellRefiner cr, PetscInt rt, PetscInt p, PetscInt *rp)
3356 {
3357   IS              rtIS;
3358   const PetscInt *points;
3359   PetscInt        n;
3360   PetscErrorCode  ierr;
3361 
3362   PetscFunctionBegin;
3363   /* TODO Move this inside the DMLabel so that I do not have to create the IS */
3364   ierr = DMLabelGetStratumIS(cr->refineType, rt, &rtIS);CHKERRQ(ierr);
3365   ierr = ISGetLocalSize(rtIS, &n);CHKERRQ(ierr);
3366   ierr = ISGetIndices(rtIS, &points);CHKERRQ(ierr);
3367   ierr = PetscFindInt(p, n, points, rp);CHKERRQ(ierr);
3368   ierr = ISRestoreIndices(rtIS, &points);CHKERRQ(ierr);
3369   ierr = ISDestroy(&rtIS);CHKERRQ(ierr);
3370   PetscFunctionReturn(0);
3371 }
3372 
3373 /*
3374   DMPlexCellRefinerGetNewPoint - Get the number of a point in the refined mesh based on information from the original mesh.
3375 
3376   Not collective
3377 
3378   Input Parameters:
3379 + cr    - The cell refiner
3380 . ct    - The type of the original point which produces the new point
3381 . ctNew - The type of the new point
3382 . p     - The original point which produces the new point
3383 - r     - The replica number of the new point, meaning it is the rth point of type ctNew produced from p
3384 
3385   Output Parameters:
3386 . pNew  - The new point number
3387 
3388   Level: developer
3389 
3390 .seealso: DMPlexCellRefinerRefine()
3391 */
3392 PetscErrorCode DMPlexCellRefinerGetNewPoint(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType ctNew, PetscInt p, PetscInt r, PetscInt *pNew)
3393 {
3394   DMPolytopeType *rct;
3395   PetscInt       *rsize, *cone, *ornt;
3396   PetscInt       rt, Nct, n, off, rp;
3397   PetscInt       ctS  = cr->ctStart[ct],       ctE  = cr->ctStart[cr->ctOrder[cr->ctOrderInv[ct]+1]];
3398   PetscInt       ctSN = cr->ctStartNew[ctNew], ctEN = cr->ctStartNew[cr->ctOrder[cr->ctOrderInv[ctNew]+1]];
3399   PetscInt       newp = ctSN, cind;
3400   PetscErrorCode ierr;
3401 
3402   PetscFunctionBeginHot;
3403   if ((p < ctS) || (p >= ctE)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a %s [%D, %D)", p, DMPolytopeTypes[ct], ctS, ctE);
3404   ierr = DMPlexCellRefinerRefine(cr, ct, p, &rt, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
3405   if (cr->refineType) {
3406     /* TODO Make this a function in DMLabel */
3407     {
3408       IS              rtIS;
3409       const PetscInt *reftypes;
3410       PetscInt        Nrt;
3411 
3412       ierr = DMLabelGetNumValues(cr->refineType, &Nrt);CHKERRQ(ierr);
3413       ierr = DMLabelGetValueIS(cr->refineType, &rtIS);CHKERRQ(ierr);
3414       ierr = ISGetIndices(rtIS, &reftypes);CHKERRQ(ierr);
3415       for (cind = 0; cind < Nrt; ++cind) if (reftypes[cind] == rt) break;
3416       if (cind >= Nrt) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unable to locate refine type %D", rt);
3417       ierr = ISRestoreIndices(rtIS, &reftypes);CHKERRQ(ierr);
3418       ierr = ISDestroy(&rtIS);CHKERRQ(ierr);
3419     }
3420     ierr = DMPlexCellRefinerGetReducedPointNumber(cr, rt, p, &rp);CHKERRQ(ierr);
3421     if (rp < 0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s point %D does not have refine type %D", DMPolytopeTypes[ct], p, rt);
3422   } else {
3423     cind = ct;
3424     rp   = p - ctS;
3425   }
3426   off = cr->offset[cind*DM_NUM_POLYTOPES + ctNew];
3427   if (off < 0) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s (%D) of point %D does not produce type %s", DMPolytopeTypes[ct], rt, p, DMPolytopeTypes[ctNew]);
3428   newp += off;
3429   for (n = 0; n < Nct; ++n) {
3430     if (rct[n] == ctNew) {
3431       if (rsize[n] && r >= rsize[n])
3432         SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Replica number %D should be in [0, %D) for subcell type %s in cell type %s", r, rsize[n], DMPolytopeTypes[rct[n]], DMPolytopeTypes[ct]);
3433       newp += rp * rsize[n] + r;
3434       break;
3435     }
3436   }
3437 
3438   if ((newp < ctSN) || (newp >= ctEN)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "New point %D is not a %s [%D, %D)", newp, DMPolytopeTypes[ctNew], ctSN, ctEN);
3439   *pNew = newp;
3440   PetscFunctionReturn(0);
3441 }
3442 
3443 static PetscErrorCode DMPlexCellRefinerSetConeSizes(DMPlexCellRefiner cr, DM rdm)
3444 {
3445   DM              dm = cr->dm;
3446   PetscInt        pStart, pEnd, p, pNew;
3447   PetscErrorCode  ierr;
3448 
3449   PetscFunctionBegin;
3450   /* Must create the celltype label here so that we do not automatically try to compute the types */
3451   ierr = DMCreateLabel(rdm, "celltype");CHKERRQ(ierr);
3452   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3453   for (p = pStart; p < pEnd; ++p) {
3454     DMPolytopeType  ct;
3455     DMPolytopeType *rct;
3456     PetscInt       *rsize, *rcone, *rornt;
3457     PetscInt        Nct, n, r;
3458 
3459     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
3460     ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
3461     for (n = 0; n < Nct; ++n) {
3462       for (r = 0; r < rsize[n]; ++r) {
3463         ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
3464         ierr = DMPlexSetConeSize(rdm, pNew, DMPolytopeTypeGetConeSize(rct[n]));CHKERRQ(ierr);
3465         ierr = DMPlexSetCellType(rdm, pNew, rct[n]);CHKERRQ(ierr);
3466       }
3467     }
3468   }
3469   {
3470     DMLabel  ctLabel;
3471     DM_Plex *plex = (DM_Plex *) rdm->data;
3472 
3473     ierr = DMPlexGetCellTypeLabel(rdm, &ctLabel);CHKERRQ(ierr);
3474     ierr = PetscObjectStateGet((PetscObject) ctLabel, &plex->celltypeState);CHKERRQ(ierr);
3475   }
3476   PetscFunctionReturn(0);
3477 }
3478 
3479 static PetscErrorCode DMPlexCellRefinerSetCones(DMPlexCellRefiner cr, DM rdm)
3480 {
3481   DM             dm = cr->dm;
3482   DMPolytopeType ct;
3483   PetscInt      *coneNew, *orntNew;
3484   PetscInt       maxConeSize = 0, pStart, pEnd, p, pNew;
3485   PetscErrorCode ierr;
3486 
3487   PetscFunctionBegin;
3488   for (p = 0; p < DM_NUM_POLYTOPES; ++p) maxConeSize = PetscMax(maxConeSize, DMPolytopeTypeGetConeSize((DMPolytopeType) p));
3489   ierr = PetscMalloc2(maxConeSize, &coneNew, maxConeSize, &orntNew);CHKERRQ(ierr);
3490   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3491   for (p = pStart; p < pEnd; ++p) {
3492     const PetscInt *cone, *ornt;
3493     PetscInt        coff, ooff, c;
3494     DMPolytopeType *rct;
3495     PetscInt       *rsize, *rcone, *rornt;
3496     PetscInt        Nct, n, r;
3497     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
3498     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
3499     ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr);
3500     ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
3501     for (n = 0, coff = 0, ooff = 0; n < Nct; ++n) {
3502       const DMPolytopeType ctNew    = rct[n];
3503       const PetscInt       csizeNew = DMPolytopeTypeGetConeSize(ctNew);
3504 
3505       for (r = 0; r < rsize[n]; ++r) {
3506         /* pNew is a subcell produced by subdividing p */
3507         ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
3508         for (c = 0; c < csizeNew; ++c) {
3509           PetscInt             ppp   = -1;                             /* Parent Parent point: Parent of point pp */
3510           PetscInt             pp    = p;                              /* Parent point: Point in the original mesh producing new cone point */
3511           PetscInt             po    = 0;                              /* Orientation of parent point pp in parent parent point ppp */
3512           DMPolytopeType       pct   = ct;                             /* Parent type: Cell type for parent of new cone point */
3513           const PetscInt      *pcone = cone;                           /* Parent cone: Cone of parent point pp */
3514           PetscInt             pr    = -1;                             /* Replica number of pp that produces new cone point  */
3515           const DMPolytopeType ft    = (DMPolytopeType) rcone[coff++]; /* Cell type for new cone point of pNew */
3516           const PetscInt       fn    = rcone[coff++];                  /* Number of cones of p that need to be taken when producing new cone point */
3517           PetscInt             fo    = rornt[ooff++];                  /* Orientation of new cone point in pNew */
3518           PetscInt             lc;
3519 
3520           /* Get the type (pct) and point number (pp) of the parent point in the original mesh which produces this cone point */
3521           for (lc = 0; lc < fn; ++lc) {
3522             const PetscInt *ppornt;
3523             PetscInt        pcp;
3524 
3525             ierr = DMPolytopeMapCell(pct, po, rcone[coff++], &pcp);CHKERRQ(ierr);
3526             ppp  = pp;
3527             pp   = pcone[pcp];
3528             ierr = DMPlexGetCellType(dm, pp, &pct);CHKERRQ(ierr);
3529             ierr = DMPlexGetCone(dm, pp, &pcone);CHKERRQ(ierr);
3530             ierr = DMPlexGetConeOrientation(dm, ppp, &ppornt);CHKERRQ(ierr);
3531             if (po <  0 && pct != DM_POLYTOPE_POINT) {
3532               const PetscInt pornt   = ppornt[pcp];
3533               const PetscInt pcsize  = DMPolytopeTypeGetConeSize(pct);
3534               const PetscInt pcstart = pornt < 0 ? -(pornt+1) : pornt;
3535               const PetscInt rcstart = (pcstart+pcsize-1)%pcsize;
3536               po = pornt < 0 ? -(rcstart+1) : rcstart;
3537             } else {
3538               po = ppornt[pcp];
3539             }
3540           }
3541           pr = rcone[coff++];
3542           /* Orientation po of pp maps (pr, fo) -> (pr', fo') */
3543           ierr = DMPlexCellRefinerMapSubcells(cr, pct, pp, po, ft, pr, fo, &pr, &fo);CHKERRQ(ierr);
3544           ierr = DMPlexCellRefinerGetNewPoint(cr, pct, ft, pp, pr, &coneNew[c]);CHKERRQ(ierr);
3545           orntNew[c] = fo;
3546         }
3547         ierr = DMPlexSetCone(rdm, pNew, coneNew);CHKERRQ(ierr);
3548         ierr = DMPlexSetConeOrientation(rdm, pNew, orntNew);CHKERRQ(ierr);
3549       }
3550     }
3551   }
3552   ierr = PetscFree2(coneNew, orntNew);CHKERRQ(ierr);
3553   ierr = DMViewFromOptions(rdm, NULL, "-rdm_view");CHKERRQ(ierr);
3554   ierr = DMPlexSymmetrize(rdm);CHKERRQ(ierr);
3555   ierr = DMPlexStratify(rdm);CHKERRQ(ierr);
3556   PetscFunctionReturn(0);
3557 }
3558 
3559 static PetscErrorCode DMPlexCellRefinerGetCoordinateFE(DMPlexCellRefiner cr, DMPolytopeType ct, PetscFE *fe)
3560 {
3561   PetscErrorCode ierr;
3562 
3563   PetscFunctionBegin;
3564   if (!cr->coordFE[ct]) {
3565     PetscInt  dim, cdim;
3566     PetscBool isSimplex;
3567 
3568     switch (ct) {
3569       case DM_POLYTOPE_SEGMENT:       dim = 1; isSimplex = PETSC_TRUE;  break;
3570       case DM_POLYTOPE_TRIANGLE:      dim = 2; isSimplex = PETSC_TRUE;  break;
3571       case DM_POLYTOPE_QUADRILATERAL: dim = 2; isSimplex = PETSC_FALSE; break;
3572       case DM_POLYTOPE_TETRAHEDRON:   dim = 3; isSimplex = PETSC_TRUE;  break;
3573       case DM_POLYTOPE_HEXAHEDRON:    dim = 3; isSimplex = PETSC_FALSE; break;
3574       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No coordinate FE for cell type %s", DMPolytopeTypes[ct]);
3575     }
3576     ierr = DMGetCoordinateDim(cr->dm, &cdim);CHKERRQ(ierr);
3577     ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, cdim, isSimplex, 1, PETSC_DETERMINE, &cr->coordFE[ct]);CHKERRQ(ierr);
3578     {
3579       PetscDualSpace  dsp;
3580       PetscQuadrature quad;
3581       DM              K;
3582       PetscFEGeom    *cg;
3583       PetscReal      *Xq, *xq, *wq;
3584       PetscInt        Nq, q;
3585 
3586       ierr = DMPlexCellRefinerGetCellVertices(cr, ct, &Nq, &Xq);CHKERRQ(ierr);
3587       ierr = PetscMalloc1(Nq*cdim, &xq);CHKERRQ(ierr);
3588       for (q = 0; q < Nq*cdim; ++q) xq[q] = Xq[q];
3589       ierr = PetscMalloc1(Nq, &wq);CHKERRQ(ierr);
3590       for (q = 0; q < Nq; ++q) wq[q] = 1.0;
3591       ierr = PetscQuadratureCreate(PETSC_COMM_SELF, &quad);CHKERRQ(ierr);
3592       ierr = PetscQuadratureSetData(quad, dim, 1, Nq, xq, wq);CHKERRQ(ierr);
3593       ierr = PetscFESetQuadrature(cr->coordFE[ct], quad);CHKERRQ(ierr);
3594 
3595       ierr = PetscFEGetDualSpace(cr->coordFE[ct], &dsp);CHKERRQ(ierr);
3596       ierr = PetscDualSpaceGetDM(dsp, &K);CHKERRQ(ierr);
3597       ierr = PetscFEGeomCreate(quad, 1, cdim, PETSC_FALSE, &cr->refGeom[ct]);CHKERRQ(ierr);
3598       cg   = cr->refGeom[ct];
3599       ierr = DMPlexComputeCellGeometryFEM(K, 0, NULL, cg->v, cg->J, cg->invJ, cg->detJ);CHKERRQ(ierr);
3600       ierr = PetscQuadratureDestroy(&quad);CHKERRQ(ierr);
3601     }
3602   }
3603   *fe = cr->coordFE[ct];
3604   PetscFunctionReturn(0);
3605 }
3606 
3607 /*
3608   DMPlexCellRefinerMapLocalizedCoordinates - Given a cell of type ct with localized coordinates x, we generate localized coordinates xr for subcell r of type rct.
3609 
3610   Not collective
3611 
3612   Input Parameters:
3613 + cr  - The DMPlexCellRefiner
3614 . ct  - The type of the parent cell
3615 . rct - The type of the produced cell
3616 . r   - The index of the produced cell
3617 - x   - The localized coordinates for the parent cell
3618 
3619   Output Parameter:
3620 . xr  - The localized coordinates for the produced cell
3621 
3622   Level: developer
3623 
3624 .seealso: DMPlexCellRefinerSetCoordinates()
3625 */
3626 static PetscErrorCode DMPlexCellRefinerMapLocalizedCoordinates(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, const PetscScalar x[], PetscScalar xr[])
3627 {
3628   PetscFE        fe = NULL;
3629   PetscInt       cdim, Nv, v, *subcellV;
3630   PetscErrorCode ierr;
3631 
3632   PetscFunctionBegin;
3633   ierr = DMPlexCellRefinerGetCoordinateFE(cr, ct, &fe);CHKERRQ(ierr);
3634   ierr = DMPlexCellRefinerGetSubcellVertices(cr, ct, rct, r, &Nv, &subcellV);CHKERRQ(ierr);
3635   ierr = PetscFEGetNumComponents(fe, &cdim);CHKERRQ(ierr);
3636   for (v = 0; v < Nv; ++v) {
3637     ierr = PetscFEInterpolate_Static(fe, x, cr->refGeom[ct], subcellV[v], &xr[v*cdim]);CHKERRQ(ierr);
3638   }
3639   PetscFunctionReturn(0);
3640 }
3641 
3642 static PetscErrorCode DMPlexCellRefinerSetCoordinates(DMPlexCellRefiner cr, DM rdm)
3643 {
3644   DM                    dm = cr->dm, cdm;
3645   PetscSection          coordSection, coordSectionNew;
3646   Vec                   coordsLocal, coordsLocalNew;
3647   const PetscScalar    *coords;
3648   PetscScalar          *coordsNew;
3649   const DMBoundaryType *bd;
3650   const PetscReal      *maxCell, *L;
3651   PetscBool             isperiodic, localizeVertices = PETSC_FALSE, localizeCells = PETSC_FALSE;
3652   PetscInt              dE, d, cStart, cEnd, c, vStartNew, vEndNew, v, pStart, pEnd, p, ocStart, ocEnd;
3653   PetscErrorCode        ierr;
3654 
3655   PetscFunctionBegin;
3656   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3657   ierr = DMGetPeriodicity(dm, &isperiodic, &maxCell, &L, &bd);CHKERRQ(ierr);
3658   /* Determine if we need to localize coordinates when generating them */
3659   if (isperiodic) {
3660     localizeVertices = PETSC_TRUE;
3661     if (!maxCell) {
3662       PetscBool localized;
3663       ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
3664       if (!localized) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Cannot refine a periodic mesh if coordinates have not been localized");
3665       localizeCells = PETSC_TRUE;
3666     }
3667   }
3668 
3669   ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
3670   ierr = PetscSectionGetFieldComponents(coordSection, 0, &dE);CHKERRQ(ierr);
3671   if (maxCell) {
3672     PetscReal maxCellNew[3];
3673 
3674     for (d = 0; d < dE; ++d) maxCellNew[d] = maxCell[d]/2.0;
3675     ierr = DMSetPeriodicity(rdm, isperiodic, maxCellNew, L, bd);CHKERRQ(ierr);
3676   } else {
3677     ierr = DMSetPeriodicity(rdm, isperiodic, maxCell, L, bd);CHKERRQ(ierr);
3678   }
3679   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &coordSectionNew);CHKERRQ(ierr);
3680   ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr);
3681   ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dE);CHKERRQ(ierr);
3682   ierr = DMPlexGetDepthStratum(rdm, 0, &vStartNew, &vEndNew);CHKERRQ(ierr);
3683   if (localizeCells) {ierr = PetscSectionSetChart(coordSectionNew, 0,         vEndNew);CHKERRQ(ierr);}
3684   else               {ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vEndNew);CHKERRQ(ierr);}
3685 
3686   /* Localization should be inherited */
3687   /*   Stefano calculates parent cells for each new cell for localization */
3688   /*   Localized cells need coordinates of closure */
3689   for (v = vStartNew; v < vEndNew; ++v) {
3690     ierr = PetscSectionSetDof(coordSectionNew, v, dE);CHKERRQ(ierr);
3691     ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dE);CHKERRQ(ierr);
3692   }
3693   if (localizeCells) {
3694     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
3695     for (c = cStart; c < cEnd; ++c) {
3696       PetscInt dof;
3697 
3698       ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr);
3699       if (dof) {
3700         DMPolytopeType  ct;
3701         DMPolytopeType *rct;
3702         PetscInt       *rsize, *rcone, *rornt;
3703         PetscInt        dim, cNew, Nct, n, r;
3704 
3705         ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
3706         dim  = DMPolytopeTypeGetDim(ct);
3707         ierr = DMPlexCellRefinerRefine(cr, ct, c, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
3708         /* This allows for different cell types */
3709         for (n = 0; n < Nct; ++n) {
3710           if (dim != DMPolytopeTypeGetDim(rct[n])) continue;
3711           for (r = 0; r < rsize[n]; ++r) {
3712             PetscInt *closure = NULL;
3713             PetscInt  clSize, cl, Nv = 0;
3714 
3715             ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], c, r, &cNew);CHKERRQ(ierr);
3716             ierr = DMPlexGetTransitiveClosure(rdm, cNew, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
3717             for (cl = 0; cl < clSize*2; cl += 2) {if ((closure[cl] >= vStartNew) && (closure[cl] < vEndNew)) ++Nv;}
3718             ierr = DMPlexRestoreTransitiveClosure(rdm, cNew, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
3719             ierr = PetscSectionSetDof(coordSectionNew, cNew, Nv * dE);CHKERRQ(ierr);
3720             ierr = PetscSectionSetFieldDof(coordSectionNew, cNew, 0, Nv * dE);CHKERRQ(ierr);
3721           }
3722         }
3723       }
3724     }
3725   }
3726   ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr);
3727   ierr = DMViewFromOptions(dm, NULL, "-coarse_dm_view");CHKERRQ(ierr);
3728   ierr = DMSetCoordinateSection(rdm, PETSC_DETERMINE, coordSectionNew);CHKERRQ(ierr);
3729   {
3730     VecType     vtype;
3731     PetscInt    coordSizeNew, bs;
3732     const char *name;
3733 
3734     ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
3735     ierr = VecCreate(PETSC_COMM_SELF, &coordsLocalNew);CHKERRQ(ierr);
3736     ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr);
3737     ierr = VecSetSizes(coordsLocalNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr);
3738     ierr = PetscObjectGetName((PetscObject) coordsLocal, &name);CHKERRQ(ierr);
3739     ierr = PetscObjectSetName((PetscObject) coordsLocalNew, name);CHKERRQ(ierr);
3740     ierr = VecGetBlockSize(coordsLocal, &bs);CHKERRQ(ierr);
3741     ierr = VecSetBlockSize(coordsLocalNew, bs);CHKERRQ(ierr);
3742     ierr = VecGetType(coordsLocal, &vtype);CHKERRQ(ierr);
3743     ierr = VecSetType(coordsLocalNew, vtype);CHKERRQ(ierr);
3744   }
3745   ierr = VecGetArrayRead(coordsLocal, &coords);CHKERRQ(ierr);
3746   ierr = VecGetArray(coordsLocalNew, &coordsNew);CHKERRQ(ierr);
3747   ierr = PetscSectionGetChart(coordSection, &ocStart, &ocEnd);CHKERRQ(ierr);
3748   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3749   /* First set coordinates for vertices*/
3750   for (p = pStart; p < pEnd; ++p) {
3751     DMPolytopeType  ct;
3752     DMPolytopeType *rct;
3753     PetscInt       *rsize, *rcone, *rornt;
3754     PetscInt        Nct, n, r;
3755     PetscBool       hasVertex = PETSC_FALSE, isLocalized = PETSC_FALSE;
3756 
3757     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
3758     ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
3759     for (n = 0; n < Nct; ++n) {
3760       if (rct[n] == DM_POLYTOPE_POINT) {hasVertex = PETSC_TRUE; break;}
3761     }
3762     if (localizeVertices && ct != DM_POLYTOPE_POINT && (p >= ocStart) && (p < ocEnd)) {
3763       PetscInt dof;
3764       ierr = PetscSectionGetDof(coordSection, p, &dof);CHKERRQ(ierr);
3765       if (dof) isLocalized = PETSC_TRUE;
3766     }
3767     if (hasVertex) {
3768       const PetscScalar *icoords = NULL;
3769       PetscScalar       *pcoords = NULL;
3770       PetscInt          Nc, Nv, v, d;
3771 
3772       ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, p, &Nc, &pcoords);CHKERRQ(ierr);
3773 
3774       icoords = pcoords;
3775       Nv      = Nc/dE;
3776       if (ct != DM_POLYTOPE_POINT) {
3777         if (localizeVertices) {
3778           PetscScalar anchor[3];
3779 
3780           for (d = 0; d < dE; ++d) anchor[d] = pcoords[d];
3781           if (!isLocalized) {
3782             for (v = 0; v < Nv; ++v) {ierr = DMLocalizeCoordinate_Internal(dm, dE, anchor, &pcoords[v*dE], &pcoords[v*dE]);CHKERRQ(ierr);}
3783           } else {
3784             Nv = Nc/(2*dE);
3785             icoords = pcoords + Nv*dE;
3786             for (v = Nv; v < Nv*2; ++v) {ierr = DMLocalizeCoordinate_Internal(dm, dE, anchor, &pcoords[v*dE], &pcoords[v*dE]);CHKERRQ(ierr);}
3787           }
3788         }
3789       }
3790       for (n = 0; n < Nct; ++n) {
3791         if (rct[n] != DM_POLYTOPE_POINT) continue;
3792         for (r = 0; r < rsize[n]; ++r) {
3793           PetscScalar vcoords[3];
3794           PetscInt    vNew, off;
3795 
3796           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &vNew);CHKERRQ(ierr);
3797           ierr = PetscSectionGetOffset(coordSectionNew, vNew, &off);CHKERRQ(ierr);
3798           ierr = DMPlexCellRefinerMapCoordinates(cr, ct, rct[n], r, Nv, dE, icoords, vcoords);CHKERRQ(ierr);
3799           ierr = DMPlexSnapToGeomModel(dm, p, vcoords, &coordsNew[off]);CHKERRQ(ierr);
3800         }
3801       }
3802       ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, p, &Nc, &pcoords);CHKERRQ(ierr);
3803     }
3804   }
3805   /* Then set coordinates for cells by localizing */
3806   for (p = pStart; p < pEnd; ++p) {
3807     DMPolytopeType  ct;
3808     DMPolytopeType *rct;
3809     PetscInt       *rsize, *rcone, *rornt;
3810     PetscInt        Nct, n, r;
3811     PetscBool       isLocalized = PETSC_FALSE;
3812 
3813     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
3814     ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
3815     if (localizeCells && ct != DM_POLYTOPE_POINT && (p >= ocStart) && (p < ocEnd)) {
3816       PetscInt dof;
3817       ierr = PetscSectionGetDof(coordSection, p, &dof);CHKERRQ(ierr);
3818       if (dof) isLocalized = PETSC_TRUE;
3819     }
3820     if (isLocalized) {
3821       const PetscScalar *pcoords;
3822 
3823       ierr = DMPlexPointLocalRead(cdm, p, coords, &pcoords);CHKERRQ(ierr);
3824       for (n = 0; n < Nct; ++n) {
3825         const PetscInt Nr = rsize[n];
3826 
3827         if (DMPolytopeTypeGetDim(ct) != DMPolytopeTypeGetDim(rct[n])) continue;
3828         for (r = 0; r < Nr; ++r) {
3829           PetscInt pNew, offNew;
3830 
3831           /* It looks like Stefano and Lisandro are allowing localized coordinates without defining the periodic boundary, which means that
3832              DMLocalizeCoordinate_Internal() will not work. Localized coordinates will have to have obtained by the affine map of the larger
3833              cell to the ones it produces. */
3834           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
3835           ierr = PetscSectionGetOffset(coordSectionNew, pNew, &offNew);CHKERRQ(ierr);
3836           ierr = DMPlexCellRefinerMapLocalizedCoordinates(cr, ct, rct[n], r, pcoords, &coordsNew[offNew]);CHKERRQ(ierr);
3837         }
3838       }
3839     }
3840   }
3841   ierr = VecRestoreArrayRead(coordsLocal, &coords);CHKERRQ(ierr);
3842   ierr = VecRestoreArray(coordsLocalNew, &coordsNew);CHKERRQ(ierr);
3843   ierr = DMSetCoordinatesLocal(rdm, coordsLocalNew);CHKERRQ(ierr);
3844   /* TODO Stefano has a final reduction if some hybrid coordinates cannot be found. (needcoords) Should not be needed. */
3845   ierr = VecDestroy(&coordsLocalNew);CHKERRQ(ierr);
3846   ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr);
3847   if (!localizeCells) {ierr = DMLocalizeCoordinates(rdm);CHKERRQ(ierr);}
3848   PetscFunctionReturn(0);
3849 }
3850 
3851 /*@
3852   DMPlexCreateProcessSF - Create an SF which just has process connectivity
3853 
3854   Collective on dm
3855 
3856   Input Parameters:
3857 + dm      - The DM
3858 - sfPoint - The PetscSF which encodes point connectivity
3859 
3860   Output Parameters:
3861 + processRanks - A list of process neighbors, or NULL
3862 - sfProcess    - An SF encoding the process connectivity, or NULL
3863 
3864   Level: developer
3865 
3866 .seealso: PetscSFCreate(), DMPlexCreateTwoSidedProcessSF()
3867 @*/
3868 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
3869 {
3870   PetscInt           numRoots, numLeaves, l;
3871   const PetscInt    *localPoints;
3872   const PetscSFNode *remotePoints;
3873   PetscInt          *localPointsNew;
3874   PetscSFNode       *remotePointsNew;
3875   PetscInt          *ranks, *ranksNew;
3876   PetscMPIInt        size;
3877   PetscErrorCode     ierr;
3878 
3879   PetscFunctionBegin;
3880   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3881   PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2);
3882   if (processRanks) {PetscValidPointer(processRanks, 3);}
3883   if (sfProcess)    {PetscValidPointer(sfProcess, 4);}
3884   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRMPI(ierr);
3885   ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
3886   ierr = PetscMalloc1(numLeaves, &ranks);CHKERRQ(ierr);
3887   for (l = 0; l < numLeaves; ++l) {
3888     ranks[l] = remotePoints[l].rank;
3889   }
3890   ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr);
3891   ierr = PetscMalloc1(numLeaves, &ranksNew);CHKERRQ(ierr);
3892   ierr = PetscMalloc1(numLeaves, &localPointsNew);CHKERRQ(ierr);
3893   ierr = PetscMalloc1(numLeaves, &remotePointsNew);CHKERRQ(ierr);
3894   for (l = 0; l < numLeaves; ++l) {
3895     ranksNew[l]              = ranks[l];
3896     localPointsNew[l]        = l;
3897     remotePointsNew[l].index = 0;
3898     remotePointsNew[l].rank  = ranksNew[l];
3899   }
3900   ierr = PetscFree(ranks);CHKERRQ(ierr);
3901   if (processRanks) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);}
3902   else              {ierr = PetscFree(ranksNew);CHKERRQ(ierr);}
3903   if (sfProcess) {
3904     ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr);
3905     ierr = PetscObjectSetName((PetscObject) *sfProcess, "Process SF");CHKERRQ(ierr);
3906     ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr);
3907     ierr = PetscSFSetGraph(*sfProcess, size, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
3908   }
3909   PetscFunctionReturn(0);
3910 }
3911 
3912 static PetscErrorCode DMPlexCellRefinerCreateSF(DMPlexCellRefiner cr, DM rdm)
3913 {
3914   DM                 dm = cr->dm;
3915   DMPlexCellRefiner *crRem;
3916   PetscSF            sf, sfNew, sfProcess;
3917   IS                 processRanks;
3918   MPI_Datatype       ctType;
3919   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
3920   const PetscInt    *localPoints, *neighbors;
3921   const PetscSFNode *remotePoints;
3922   PetscInt          *localPointsNew;
3923   PetscSFNode       *remotePointsNew;
3924   PetscInt          *ctStartRem, *ctStartNewRem;
3925   PetscInt           ctSize = DM_NUM_POLYTOPES+1, numNeighbors, n, pStartNew, pEndNew, pNew, pNewRem;
3926   /* Brute force algorithm */
3927   PetscSF            rsf;
3928   PetscSection       s;
3929   const PetscInt    *rootdegree;
3930   PetscInt          *rootPointsNew, *remoteOffsets;
3931   PetscInt           numPointsNew, pStart, pEnd, p;
3932   PetscErrorCode     ierr;
3933 
3934   PetscFunctionBegin;
3935   ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr);
3936   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
3937   ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr);
3938   /* Calculate size of new SF */
3939   ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
3940   if (numRoots < 0) PetscFunctionReturn(0);
3941   for (l = 0; l < numLeaves; ++l) {
3942     const PetscInt  p = localPoints[l];
3943     DMPolytopeType  ct;
3944     DMPolytopeType *rct;
3945     PetscInt       *rsize, *rcone, *rornt;
3946     PetscInt        Nct, n;
3947 
3948     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
3949     ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
3950     for (n = 0; n < Nct; ++n) {
3951       numLeavesNew += rsize[n];
3952     }
3953   }
3954   if (cr->refineType) {
3955     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3956     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &s);CHKERRQ(ierr);
3957     ierr = PetscSectionSetChart(s, pStart, pEnd);CHKERRQ(ierr);
3958     for (p = pStart; p < pEnd; ++p) {
3959       DMPolytopeType  ct;
3960       DMPolytopeType *rct;
3961       PetscInt       *rsize, *rcone, *rornt;
3962       PetscInt        Nct, n;
3963 
3964       ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
3965       ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
3966       for (n = 0; n < Nct; ++n) {
3967         ierr = PetscSectionAddDof(s, p, rsize[n]);CHKERRQ(ierr);
3968       }
3969     }
3970     ierr = PetscSectionSetUp(s);CHKERRQ(ierr);
3971     ierr = PetscSectionGetStorageSize(s, &numPointsNew);CHKERRQ(ierr);
3972     ierr = PetscSFCreateRemoteOffsets(sf, s, s, &remoteOffsets);CHKERRQ(ierr);
3973     ierr = PetscSFCreateSectionSF(sf, s, remoteOffsets, s, &rsf);CHKERRQ(ierr);
3974     ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
3975     ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr);
3976     ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr);
3977     ierr = PetscMalloc1(numPointsNew, &rootPointsNew);CHKERRQ(ierr);
3978     for (p = 0; p < numPointsNew; ++p) rootPointsNew[p] = -1;
3979     for (p = pStart; p < pEnd; ++p) {
3980       DMPolytopeType  ct;
3981       DMPolytopeType *rct;
3982       PetscInt       *rsize, *rcone, *rornt;
3983       PetscInt        Nct, n, r, off;
3984 
3985       if (!rootdegree[p-pStart]) continue;
3986       ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr);
3987       ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
3988       ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
3989       for (n = 0, m = 0; n < Nct; ++n) {
3990         for (r = 0; r < rsize[n]; ++r, ++m) {
3991           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
3992           rootPointsNew[off+m] = pNew;
3993         }
3994       }
3995     }
3996     ierr = PetscSFBcastBegin(rsf, MPIU_INT, rootPointsNew, rootPointsNew,MPI_REPLACE);CHKERRQ(ierr);
3997     ierr = PetscSFBcastEnd(rsf, MPIU_INT, rootPointsNew, rootPointsNew,MPI_REPLACE);CHKERRQ(ierr);
3998     ierr = PetscSFDestroy(&rsf);CHKERRQ(ierr);
3999     ierr = PetscMalloc1(numLeavesNew, &localPointsNew);CHKERRQ(ierr);
4000     ierr = PetscMalloc1(numLeavesNew, &remotePointsNew);CHKERRQ(ierr);
4001     for (l = 0, m = 0; l < numLeaves; ++l) {
4002       const PetscInt  p = localPoints[l];
4003       DMPolytopeType  ct;
4004       DMPolytopeType *rct;
4005       PetscInt       *rsize, *rcone, *rornt;
4006       PetscInt        Nct, n, r, q, off;
4007 
4008       ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr);
4009       ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
4010       ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
4011       for (n = 0, q = 0; n < Nct; ++n) {
4012         for (r = 0; r < rsize[n]; ++r, ++m, ++q) {
4013           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
4014           localPointsNew[m]        = pNew;
4015           remotePointsNew[m].index = rootPointsNew[off+q];
4016           remotePointsNew[m].rank  = remotePoints[l].rank;
4017         }
4018       }
4019     }
4020     ierr = PetscSectionDestroy(&s);CHKERRQ(ierr);
4021     ierr = PetscFree(rootPointsNew);CHKERRQ(ierr);
4022   } else {
4023     /* Communicate ctStart and cStartNew for each remote rank */
4024     ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr);
4025     ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr);
4026     ierr = PetscMalloc2(ctSize*numNeighbors, &ctStartRem, ctSize*numNeighbors, &ctStartNewRem);CHKERRQ(ierr);
4027     ierr = MPI_Type_contiguous(ctSize, MPIU_INT, &ctType);CHKERRMPI(ierr);
4028     ierr = MPI_Type_commit(&ctType);CHKERRMPI(ierr);
4029     ierr = PetscSFBcastBegin(sfProcess, ctType, cr->ctStart, ctStartRem,MPI_REPLACE);CHKERRQ(ierr);
4030     ierr = PetscSFBcastEnd(sfProcess, ctType, cr->ctStart, ctStartRem,MPI_REPLACE);CHKERRQ(ierr);
4031     ierr = PetscSFBcastBegin(sfProcess, ctType, cr->ctStartNew, ctStartNewRem,MPI_REPLACE);CHKERRQ(ierr);
4032     ierr = PetscSFBcastEnd(sfProcess, ctType, cr->ctStartNew, ctStartNewRem,MPI_REPLACE);CHKERRQ(ierr);
4033     ierr = MPI_Type_free(&ctType);CHKERRMPI(ierr);
4034     ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr);
4035     ierr = PetscMalloc1(numNeighbors, &crRem);CHKERRQ(ierr);
4036     for (n = 0; n < numNeighbors; ++n) {
4037       ierr = DMPlexCellRefinerCreate(dm, &crRem[n]);CHKERRQ(ierr);
4038       ierr = DMPlexCellRefinerSetStarts(crRem[n], &ctStartRem[n*ctSize], &ctStartNewRem[n*ctSize]);
4039       ierr = DMPlexCellRefinerSetUp(crRem[n]);CHKERRQ(ierr);
4040     }
4041     ierr = PetscFree2(ctStartRem, ctStartNewRem);CHKERRQ(ierr);
4042     /* Calculate new point SF */
4043     ierr = PetscMalloc1(numLeavesNew, &localPointsNew);CHKERRQ(ierr);
4044     ierr = PetscMalloc1(numLeavesNew, &remotePointsNew);CHKERRQ(ierr);
4045     ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr);
4046     for (l = 0, m = 0; l < numLeaves; ++l) {
4047       PetscInt        p       = localPoints[l];
4048       PetscInt        pRem    = remotePoints[l].index;
4049       PetscMPIInt     rankRem = remotePoints[l].rank;
4050       DMPolytopeType  ct;
4051       DMPolytopeType *rct;
4052       PetscInt       *rsize, *rcone, *rornt;
4053       PetscInt        neighbor, Nct, n, r;
4054 
4055       ierr = PetscFindInt(rankRem, numNeighbors, neighbors, &neighbor);CHKERRQ(ierr);
4056       if (neighbor < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %D", rankRem);
4057       ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
4058       ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
4059       for (n = 0; n < Nct; ++n) {
4060         for (r = 0; r < rsize[n]; ++r) {
4061           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
4062           ierr = DMPlexCellRefinerGetNewPoint(crRem[neighbor], ct, rct[n], pRem, r, &pNewRem);CHKERRQ(ierr);
4063           localPointsNew[m]        = pNew;
4064           remotePointsNew[m].index = pNewRem;
4065           remotePointsNew[m].rank  = rankRem;
4066           ++m;
4067         }
4068       }
4069     }
4070     for (n = 0; n < numNeighbors; ++n) {ierr = DMPlexCellRefinerDestroy(&crRem[n]);CHKERRQ(ierr);}
4071     ierr = PetscFree(crRem);CHKERRQ(ierr);
4072     if (m != numLeavesNew) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of leaf point %D should be %D", m, numLeavesNew);
4073     ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr);
4074     ierr = ISDestroy(&processRanks);CHKERRQ(ierr);
4075   }
4076   {
4077     PetscSFNode *rp, *rtmp;
4078     PetscInt    *lp, *idx, *ltmp, i;
4079 
4080     /* SF needs sorted leaves to correct calculate Gather */
4081     ierr = PetscMalloc1(numLeavesNew, &idx);CHKERRQ(ierr);
4082     ierr = PetscMalloc1(numLeavesNew, &lp);CHKERRQ(ierr);
4083     ierr = PetscMalloc1(numLeavesNew, &rp);CHKERRQ(ierr);
4084     for (i = 0; i < numLeavesNew; ++i) {
4085       if ((localPointsNew[i] < pStartNew) || (localPointsNew[i] >= pEndNew)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local SF point %D (%D) not in [%D, %D)", localPointsNew[i], i, pStartNew, pEndNew);
4086       idx[i] = i;
4087     }
4088     ierr = PetscSortIntWithPermutation(numLeavesNew, localPointsNew, idx);CHKERRQ(ierr);
4089     for (i = 0; i < numLeavesNew; ++i) {
4090       lp[i] = localPointsNew[idx[i]];
4091       rp[i] = remotePointsNew[idx[i]];
4092     }
4093     ltmp            = localPointsNew;
4094     localPointsNew  = lp;
4095     rtmp            = remotePointsNew;
4096     remotePointsNew = rp;
4097     ierr = PetscFree(idx);CHKERRQ(ierr);
4098     ierr = PetscFree(ltmp);CHKERRQ(ierr);
4099     ierr = PetscFree(rtmp);CHKERRQ(ierr);
4100   }
4101   ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
4102   PetscFunctionReturn(0);
4103 }
4104 
4105 static PetscErrorCode RefineLabel_Internal(DMPlexCellRefiner cr, DMLabel label, DMLabel labelNew)
4106 {
4107   DM              dm = cr->dm;
4108   IS              valueIS;
4109   const PetscInt *values;
4110   PetscInt        defVal, Nv, val;
4111   PetscErrorCode  ierr;
4112 
4113   PetscFunctionBegin;
4114   ierr = DMLabelGetDefaultValue(label, &defVal);CHKERRQ(ierr);
4115   ierr = DMLabelSetDefaultValue(labelNew, defVal);CHKERRQ(ierr);
4116   ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
4117   ierr = ISGetLocalSize(valueIS, &Nv);CHKERRQ(ierr);
4118   ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
4119   for (val = 0; val < Nv; ++val) {
4120     IS              pointIS;
4121     const PetscInt *points;
4122     PetscInt        numPoints, p;
4123 
4124     /* Ensure refined label is created with same number of strata as
4125      * original (even if no entries here). */
4126     ierr = DMLabelAddStratum(labelNew, values[val]);CHKERRQ(ierr);
4127     ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr);
4128     ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
4129     ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
4130     for (p = 0; p < numPoints; ++p) {
4131       const PetscInt  point = points[p];
4132       DMPolytopeType  ct;
4133       DMPolytopeType *rct;
4134       PetscInt       *rsize, *rcone, *rornt;
4135       PetscInt        Nct, n, r, pNew;
4136 
4137       ierr = DMPlexGetCellType(dm, point, &ct);CHKERRQ(ierr);
4138       ierr = DMPlexCellRefinerRefine(cr, ct, point, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
4139       for (n = 0; n < Nct; ++n) {
4140         for (r = 0; r < rsize[n]; ++r) {
4141           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], point, r, &pNew);CHKERRQ(ierr);
4142           ierr = DMLabelSetValue(labelNew, pNew, values[val]);CHKERRQ(ierr);
4143         }
4144       }
4145     }
4146     ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
4147     ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
4148   }
4149   ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
4150   ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
4151   PetscFunctionReturn(0);
4152 }
4153 
4154 static PetscErrorCode DMPlexCellRefinerCreateLabels(DMPlexCellRefiner cr, DM rdm)
4155 {
4156   DM             dm = cr->dm;
4157   PetscInt       numLabels, l;
4158   PetscErrorCode ierr;
4159 
4160   PetscFunctionBegin;
4161   ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
4162   for (l = 0; l < numLabels; ++l) {
4163     DMLabel         label, labelNew;
4164     const char     *lname;
4165     PetscBool       isDepth, isCellType;
4166 
4167     ierr = DMGetLabelName(dm, l, &lname);CHKERRQ(ierr);
4168     ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr);
4169     if (isDepth) continue;
4170     ierr = PetscStrcmp(lname, "celltype", &isCellType);CHKERRQ(ierr);
4171     if (isCellType) continue;
4172     ierr = DMCreateLabel(rdm, lname);CHKERRQ(ierr);
4173     ierr = DMGetLabel(dm, lname, &label);CHKERRQ(ierr);
4174     ierr = DMGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr);
4175     ierr = RefineLabel_Internal(cr, label, labelNew);CHKERRQ(ierr);
4176   }
4177   PetscFunctionReturn(0);
4178 }
4179 
4180 /* This will only work for interpolated meshes */
4181 PetscErrorCode DMPlexRefineUniform(DM dm, DMPlexCellRefiner cr, DM *dmRefined)
4182 {
4183   DM              rdm;
4184   PetscInt        dim, embedDim, depth;
4185   PetscErrorCode  ierr;
4186 
4187   PetscFunctionBegin;
4188   PetscValidHeader(cr, 1);
4189   ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr);
4190   ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr);
4191   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
4192   ierr = DMSetDimension(rdm, dim);CHKERRQ(ierr);
4193   ierr = DMGetCoordinateDim(dm, &embedDim);CHKERRQ(ierr);
4194   ierr = DMSetCoordinateDim(rdm, embedDim);CHKERRQ(ierr);
4195   /* Calculate number of new points of each depth */
4196   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
4197   if (depth >= 0 && dim != depth) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated for regular refinement");
4198   /* Step 1: Set chart */
4199   ierr = DMPlexSetChart(rdm, 0, cr->ctStartNew[cr->ctOrder[DM_NUM_POLYTOPES]]);CHKERRQ(ierr);
4200   /* Step 2: Set cone/support sizes (automatically stratifies) */
4201   ierr = DMPlexCellRefinerSetConeSizes(cr, rdm);CHKERRQ(ierr);
4202   /* Step 3: Setup refined DM */
4203   ierr = DMSetUp(rdm);CHKERRQ(ierr);
4204   /* Step 4: Set cones and supports (automatically symmetrizes) */
4205   ierr = DMPlexCellRefinerSetCones(cr, rdm);CHKERRQ(ierr);
4206   /* Step 5: Create pointSF */
4207   ierr = DMPlexCellRefinerCreateSF(cr, rdm);CHKERRQ(ierr);
4208   /* Step 6: Create labels */
4209   ierr = DMPlexCellRefinerCreateLabels(cr, rdm);CHKERRQ(ierr);
4210   /* Step 7: Set coordinates */
4211   ierr = DMPlexCellRefinerSetCoordinates(cr, rdm);CHKERRQ(ierr);
4212   *dmRefined = rdm;
4213   PetscFunctionReturn(0);
4214 }
4215 
4216 /*@
4217   DMPlexCreateCoarsePointIS - Creates an IS covering the coarse DM chart with the fine points as data
4218 
4219   Input Parameter:
4220 . dm - The coarse DM
4221 
4222   Output Parameter:
4223 . fpointIS - The IS of all the fine points which exist in the original coarse mesh
4224 
4225   Level: developer
4226 
4227 .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetSubpointIS()
4228 @*/
4229 PetscErrorCode DMPlexCreateCoarsePointIS(DM dm, IS *fpointIS)
4230 {
4231   DMPlexCellRefiner cr;
4232   PetscInt         *fpoints;
4233   PetscInt          pStart, pEnd, p, vStart, vEnd, v;
4234   PetscErrorCode    ierr;
4235 
4236   PetscFunctionBegin;
4237   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
4238   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
4239   ierr = DMPlexCellRefinerCreate(dm, &cr);CHKERRQ(ierr);
4240   ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
4241   ierr = PetscMalloc1(pEnd-pStart, &fpoints);CHKERRQ(ierr);
4242   for (p = 0; p < pEnd-pStart; ++p) fpoints[p] = -1;
4243   for (v = vStart; v < vEnd; ++v) {
4244     PetscInt vNew = -1; /* silent overzelous may be used uninitialized */
4245 
4246     ierr = DMPlexCellRefinerGetNewPoint(cr, DM_POLYTOPE_POINT, DM_POLYTOPE_POINT, p, 0, &vNew);CHKERRQ(ierr);
4247     fpoints[v-pStart] = vNew;
4248   }
4249   ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
4250   ierr = ISCreateGeneral(PETSC_COMM_SELF, pEnd-pStart, fpoints, PETSC_OWN_POINTER, fpointIS);CHKERRQ(ierr);
4251   PetscFunctionReturn(0);
4252 }
4253 
4254 /*@
4255   DMPlexSetRefinementUniform - Set the flag for uniform refinement
4256 
4257   Input Parameters:
4258 + dm - The DM
4259 - refinementUniform - The flag for uniform refinement
4260 
4261   Level: developer
4262 
4263 .seealso: DMRefine(), DMPlexGetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
4264 @*/
4265 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
4266 {
4267   DM_Plex *mesh = (DM_Plex*) dm->data;
4268 
4269   PetscFunctionBegin;
4270   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4271   mesh->refinementUniform = refinementUniform;
4272   PetscFunctionReturn(0);
4273 }
4274 
4275 /*@
4276   DMPlexGetRefinementUniform - Retrieve the flag for uniform refinement
4277 
4278   Input Parameter:
4279 . dm - The DM
4280 
4281   Output Parameter:
4282 . refinementUniform - The flag for uniform refinement
4283 
4284   Level: developer
4285 
4286 .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
4287 @*/
4288 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
4289 {
4290   DM_Plex *mesh = (DM_Plex*) dm->data;
4291 
4292   PetscFunctionBegin;
4293   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4294   PetscValidPointer(refinementUniform,  2);
4295   *refinementUniform = mesh->refinementUniform;
4296   PetscFunctionReturn(0);
4297 }
4298 
4299 /*@
4300   DMPlexSetRefinementLimit - Set the maximum cell volume for refinement
4301 
4302   Input Parameters:
4303 + dm - The DM
4304 - refinementLimit - The maximum cell volume in the refined mesh
4305 
4306   Level: developer
4307 
4308 .seealso: DMRefine(), DMPlexGetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
4309 @*/
4310 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
4311 {
4312   DM_Plex *mesh = (DM_Plex*) dm->data;
4313 
4314   PetscFunctionBegin;
4315   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4316   mesh->refinementLimit = refinementLimit;
4317   PetscFunctionReturn(0);
4318 }
4319 
4320 /*@
4321   DMPlexGetRefinementLimit - Retrieve the maximum cell volume for refinement
4322 
4323   Input Parameter:
4324 . dm - The DM
4325 
4326   Output Parameter:
4327 . refinementLimit - The maximum cell volume in the refined mesh
4328 
4329   Level: developer
4330 
4331 .seealso: DMRefine(), DMPlexSetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
4332 @*/
4333 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
4334 {
4335   DM_Plex *mesh = (DM_Plex*) dm->data;
4336 
4337   PetscFunctionBegin;
4338   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4339   PetscValidPointer(refinementLimit,  2);
4340   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
4341   *refinementLimit = mesh->refinementLimit;
4342   PetscFunctionReturn(0);
4343 }
4344 
4345 /*@
4346   DMPlexSetRefinementFunction - Set the function giving the maximum cell volume for refinement
4347 
4348   Input Parameters:
4349 + dm - The DM
4350 - refinementFunc - Function giving the maximum cell volume in the refined mesh
4351 
4352   Note: The calling sequence is refinementFunc(coords, limit)
4353 $ coords - Coordinates of the current point, usually a cell centroid
4354 $ limit  - The maximum cell volume for a cell containing this point
4355 
4356   Level: developer
4357 
4358 .seealso: DMRefine(), DMPlexGetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
4359 @*/
4360 PetscErrorCode DMPlexSetRefinementFunction(DM dm, PetscErrorCode (*refinementFunc)(const PetscReal [], PetscReal *))
4361 {
4362   DM_Plex *mesh = (DM_Plex*) dm->data;
4363 
4364   PetscFunctionBegin;
4365   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4366   mesh->refinementFunc = refinementFunc;
4367   PetscFunctionReturn(0);
4368 }
4369 
4370 /*@
4371   DMPlexGetRefinementFunction - Get the function giving the maximum cell volume for refinement
4372 
4373   Input Parameter:
4374 . dm - The DM
4375 
4376   Output Parameter:
4377 . refinementFunc - Function giving the maximum cell volume in the refined mesh
4378 
4379   Note: The calling sequence is refinementFunc(coords, limit)
4380 $ coords - Coordinates of the current point, usually a cell centroid
4381 $ limit  - The maximum cell volume for a cell containing this point
4382 
4383   Level: developer
4384 
4385 .seealso: DMRefine(), DMPlexSetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
4386 @*/
4387 PetscErrorCode DMPlexGetRefinementFunction(DM dm, PetscErrorCode (**refinementFunc)(const PetscReal [], PetscReal *))
4388 {
4389   DM_Plex *mesh = (DM_Plex*) dm->data;
4390 
4391   PetscFunctionBegin;
4392   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4393   PetscValidPointer(refinementFunc,  2);
4394   *refinementFunc = mesh->refinementFunc;
4395   PetscFunctionReturn(0);
4396 }
4397 
4398 static PetscErrorCode RefineDiscLabels_Internal(DMPlexCellRefiner cr, DM rdm)
4399 {
4400   DM             dm = cr->dm;
4401   PetscInt       Nf, f, Nds, s;
4402   PetscErrorCode ierr;
4403 
4404   PetscFunctionBegin;
4405   ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
4406   for (f = 0; f < Nf; ++f) {
4407     DMLabel     label, labelNew;
4408     PetscObject obj;
4409     const char *lname;
4410 
4411     ierr = DMGetField(rdm, f, &label, &obj);CHKERRQ(ierr);
4412     if (!label) continue;
4413     ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
4414     ierr = DMLabelCreate(PETSC_COMM_SELF, lname, &labelNew);CHKERRQ(ierr);
4415     ierr = RefineLabel_Internal(cr, label, labelNew);CHKERRQ(ierr);
4416     ierr = DMSetField_Internal(rdm, f, labelNew, obj);CHKERRQ(ierr);
4417     ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);
4418   }
4419   ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
4420   for (s = 0; s < Nds; ++s) {
4421     DMLabel     label, labelNew;
4422     const char *lname;
4423 
4424     ierr = DMGetRegionNumDS(rdm, s, &label, NULL, NULL);CHKERRQ(ierr);
4425     if (!label) continue;
4426     ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
4427     ierr = DMLabelCreate(PETSC_COMM_SELF, lname, &labelNew);CHKERRQ(ierr);
4428     ierr = RefineLabel_Internal(cr, label, labelNew);CHKERRQ(ierr);
4429     ierr = DMSetRegionNumDS(rdm, s, labelNew, NULL, NULL);CHKERRQ(ierr);
4430     ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);
4431   }
4432   PetscFunctionReturn(0);
4433 }
4434 
4435 PetscErrorCode DMPlexCellRefinerAdaptLabel(DM dm, DMLabel adaptLabel, DM *dmRefined)
4436 {
4437   DMPlexCellRefiner cr;
4438   DM                cdm, rcdm;
4439   PetscErrorCode    ierr;
4440 
4441   PetscFunctionBegin;
4442   ierr = DMPlexCellRefinerCreate(dm, &cr);CHKERRQ(ierr);
4443   cr->adaptLabel = adaptLabel;
4444   ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
4445   ierr = DMPlexRefineUniform(dm, cr, dmRefined);CHKERRQ(ierr);
4446   ierr = DMCopyDisc(dm, *dmRefined);CHKERRQ(ierr);
4447   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4448   ierr = DMGetCoordinateDM(*dmRefined, &rcdm);CHKERRQ(ierr);
4449   ierr = DMCopyDisc(cdm, rcdm);CHKERRQ(ierr);
4450   ierr = RefineDiscLabels_Internal(cr, *dmRefined);CHKERRQ(ierr);
4451   ierr = DMCopyBoundary(dm, *dmRefined);CHKERRQ(ierr);
4452   ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
4453   PetscFunctionReturn(0);
4454 }
4455 
4456 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined)
4457 {
4458   PetscBool         isUniform;
4459   DMPlexCellRefiner cr;
4460   PetscErrorCode    ierr;
4461 
4462   PetscFunctionBegin;
4463   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
4464   ierr = DMViewFromOptions(dm, NULL, "-initref_dm_view");CHKERRQ(ierr);
4465   if (isUniform) {
4466     DM        cdm, rcdm;
4467     PetscBool localized;
4468 
4469     ierr = DMPlexCellRefinerCreate(dm, &cr);CHKERRQ(ierr);
4470     ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
4471     ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
4472     ierr = DMPlexRefineUniform(dm, cr, dmRefined);CHKERRQ(ierr);
4473     ierr = DMPlexSetRegularRefinement(*dmRefined, PETSC_TRUE);CHKERRQ(ierr);
4474     ierr = DMCopyDisc(dm, *dmRefined);CHKERRQ(ierr);
4475     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4476     ierr = DMGetCoordinateDM(*dmRefined, &rcdm);CHKERRQ(ierr);
4477     ierr = DMCopyDisc(cdm, rcdm);CHKERRQ(ierr);
4478     ierr = RefineDiscLabels_Internal(cr, *dmRefined);CHKERRQ(ierr);
4479     ierr = DMCopyBoundary(dm, *dmRefined);CHKERRQ(ierr);
4480     ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
4481   } else {
4482     ierr = DMPlexRefine_Internal(dm, NULL, dmRefined);CHKERRQ(ierr);
4483   }
4484   if (*dmRefined) {
4485     ((DM_Plex *) (*dmRefined)->data)->printFEM = ((DM_Plex *) dm->data)->printFEM;
4486     ((DM_Plex *) (*dmRefined)->data)->printL2  = ((DM_Plex *) dm->data)->printL2;
4487   }
4488   PetscFunctionReturn(0);
4489 }
4490 
4491 PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM dmRefined[])
4492 {
4493   DM             cdm = dm;
4494   PetscInt       r;
4495   PetscBool      isUniform, localized;
4496   PetscErrorCode ierr;
4497 
4498   PetscFunctionBegin;
4499   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
4500   ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
4501   if (isUniform) {
4502     for (r = 0; r < nlevels; ++r) {
4503       DMPlexCellRefiner cr;
4504       DM                codm, rcodm;
4505 
4506       ierr = DMPlexCellRefinerCreate(cdm, &cr);CHKERRQ(ierr);
4507       ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
4508       ierr = DMPlexRefineUniform(cdm, cr, &dmRefined[r]);CHKERRQ(ierr);
4509       ierr = DMSetCoarsenLevel(dmRefined[r], cdm->leveldown);CHKERRQ(ierr);
4510       ierr = DMSetRefineLevel(dmRefined[r], cdm->levelup+1);CHKERRQ(ierr);
4511       ierr = DMCopyDisc(cdm, dmRefined[r]);CHKERRQ(ierr);
4512       ierr = DMGetCoordinateDM(dm, &codm);CHKERRQ(ierr);
4513       ierr = DMGetCoordinateDM(dmRefined[r], &rcodm);CHKERRQ(ierr);
4514       ierr = DMCopyDisc(codm, rcodm);CHKERRQ(ierr);
4515       ierr = RefineDiscLabels_Internal(cr, dmRefined[r]);CHKERRQ(ierr);
4516       ierr = DMCopyBoundary(cdm, dmRefined[r]);CHKERRQ(ierr);
4517       ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr);
4518       ierr = DMPlexSetRegularRefinement(dmRefined[r], PETSC_TRUE);CHKERRQ(ierr);
4519       if (dmRefined[r]) {
4520         ((DM_Plex *) (dmRefined[r])->data)->printFEM = ((DM_Plex *) dm->data)->printFEM;
4521         ((DM_Plex *) (dmRefined[r])->data)->printL2  = ((DM_Plex *) dm->data)->printL2;
4522       }
4523       cdm  = dmRefined[r];
4524       ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
4525     }
4526   } else {
4527     for (r = 0; r < nlevels; ++r) {
4528       ierr = DMRefine(cdm, PetscObjectComm((PetscObject) dm), &dmRefined[r]);CHKERRQ(ierr);
4529       ierr = DMCopyDisc(cdm, dmRefined[r]);CHKERRQ(ierr);
4530       ierr = DMCopyBoundary(cdm, dmRefined[r]);CHKERRQ(ierr);
4531       if (localized) {ierr = DMLocalizeCoordinates(dmRefined[r]);CHKERRQ(ierr);}
4532       ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr);
4533       if (dmRefined[r]) {
4534         ((DM_Plex *) (dmRefined[r])->data)->printFEM = ((DM_Plex *) dm->data)->printFEM;
4535         ((DM_Plex *) (dmRefined[r])->data)->printL2  = ((DM_Plex *) dm->data)->printL2;
4536       }
4537       cdm  = dmRefined[r];
4538     }
4539   }
4540   PetscFunctionReturn(0);
4541 }
4542