xref: /petsc/src/dm/impls/plex/plexrefine.c (revision 412e9a14abbdcfab8bb1cbfb40875fcde8c4ce26)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2*412e9a14SMatthew G. Knepley #include <petsc/private/petscfeimpl.h>  /* For PetscFEInterpolate_Static() */
375d3a19aSMatthew G. Knepley #include <petscsf.h>
475d3a19aSMatthew G. Knepley 
5*412e9a14SMatthew G. Knepley const char * const DMPlexCellRefinerTypes[] = {"Regular", "ToHex", "ToSimplex", "DMPlexCellRefinerTypes", "REFINER_", 0};
675d3a19aSMatthew G. Knepley 
709789c4cSMatthew G. Knepley /*
809789c4cSMatthew G. Knepley   Note that j and invj are non-square:
909789c4cSMatthew G. Knepley          v0 + j x_face = x_cell
1009789c4cSMatthew G. Knepley     invj (x_cell - v0) = x_face
1109789c4cSMatthew G. Knepley */
12*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetAffineFaceTransforms_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nf, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[], PetscReal *detJ[])
1309789c4cSMatthew G. Knepley {
1409789c4cSMatthew G. Knepley   /*
1509789c4cSMatthew G. Knepley    2
1609789c4cSMatthew G. Knepley    |\
1709789c4cSMatthew G. Knepley    | \
1809789c4cSMatthew G. Knepley    |  \
1909789c4cSMatthew G. Knepley    |   \
2009789c4cSMatthew G. Knepley    |    \
2109789c4cSMatthew G. Knepley    |     \
2209789c4cSMatthew G. Knepley    |      \
2309789c4cSMatthew G. Knepley    2       1
2409789c4cSMatthew G. Knepley    |        \
2509789c4cSMatthew G. Knepley    |         \
2609789c4cSMatthew G. Knepley    |          \
2709789c4cSMatthew G. Knepley    0---0-------1
28*412e9a14SMatthew G. Knepley    v0[Nf][dc]:       3 x 2
29*412e9a14SMatthew G. Knepley    J[Nf][df][dc]:    3 x 1 x 2
30*412e9a14SMatthew G. Knepley    invJ[Nf][dc][df]: 3 x 2 x 1
31*412e9a14SMatthew G. Knepley    detJ[Nf]:         3
3209789c4cSMatthew G. Knepley    */
33*412e9a14SMatthew G. Knepley   static PetscReal tri_v0[]   = {0.0, -1.0,  0.0, 0.0,  -1.0,  0.0};
34*412e9a14SMatthew G. Knepley   static PetscReal tri_J[]    = {1.0, 0.0,  -1.0, 1.0,   0.0, -1.0};
35*412e9a14SMatthew G. Knepley   static PetscReal tri_invJ[] = {1.0, 0.0,  -0.5, 0.5,   0.0, -1.0};
36*412e9a14SMatthew G. Knepley   static PetscReal tri_detJ[] = {1.0,  1.414213562373095,  1.0};
3709789c4cSMatthew G. Knepley   /*
3809789c4cSMatthew G. Knepley    3---------2---------2
3909789c4cSMatthew G. Knepley    |                   |
4009789c4cSMatthew G. Knepley    |                   |
4109789c4cSMatthew G. Knepley    |                   |
4209789c4cSMatthew G. Knepley    3                   1
4309789c4cSMatthew G. Knepley    |                   |
4409789c4cSMatthew G. Knepley    |                   |
4509789c4cSMatthew G. Knepley    |                   |
4609789c4cSMatthew G. Knepley    0---------0---------1
47*412e9a14SMatthew G. Knepley 
48*412e9a14SMatthew G. Knepley    v0[Nf][dc]:       4 x 2
49*412e9a14SMatthew G. Knepley    J[Nf][df][dc]:    4 x 1 x 2
50*412e9a14SMatthew G. Knepley    invJ[Nf][dc][df]: 4 x 2 x 1
51*412e9a14SMatthew G. Knepley    detJ[Nf]:         4
5209789c4cSMatthew G. Knepley    */
53*412e9a14SMatthew G. Knepley   static PetscReal quad_v0[]   = {0.0, -1.0,  1.0, 0.0,   0.0, 1.0  -1.0,  0.0};
54*412e9a14SMatthew G. Knepley   static PetscReal quad_J[]    = {1.0, 0.0,   0.0, 1.0,  -1.0, 0.0,  0.0, -1.0};
55*412e9a14SMatthew G. Knepley   static PetscReal quad_invJ[] = {1.0, 0.0,   0.0, 1.0,  -1.0, 0.0,  0.0, -1.0};
56*412e9a14SMatthew G. Knepley   static PetscReal quad_detJ[] = {1.0,  1.0,  1.0,  1.0};
57*412e9a14SMatthew G. Knepley 
58*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
59*412e9a14SMatthew G. Knepley   switch (ct) {
60*412e9a14SMatthew G. Knepley   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;
61*412e9a14SMatthew G. Knepley   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;
6209789c4cSMatthew G. Knepley   default:
63*412e9a14SMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
6409789c4cSMatthew G. Knepley   }
6509789c4cSMatthew G. Knepley   PetscFunctionReturn(0);
6609789c4cSMatthew G. Knepley }
6709789c4cSMatthew G. Knepley 
68bed052eaSMatthew G. Knepley /* Gets the affine map from the original cell to each subcell */
69*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetAffineTransforms_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nc, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[])
70bed052eaSMatthew G. Knepley {
71260b6d3fSMatthew G. Knepley   /*
72260b6d3fSMatthew G. Knepley    2
73260b6d3fSMatthew G. Knepley    |\
74260b6d3fSMatthew G. Knepley    | \
75260b6d3fSMatthew G. Knepley    |  \
76260b6d3fSMatthew G. Knepley    |   \
77260b6d3fSMatthew G. Knepley    | C  \
78260b6d3fSMatthew G. Knepley    |     \
79260b6d3fSMatthew G. Knepley    |      \
80260b6d3fSMatthew G. Knepley    2---1---1
81260b6d3fSMatthew G. Knepley    |\  D  / \
82260b6d3fSMatthew G. Knepley    | 2   0   \
83260b6d3fSMatthew G. Knepley    |A \ /  B  \
84260b6d3fSMatthew G. Knepley    0---0-------1
85260b6d3fSMatthew G. Knepley    */
86*412e9a14SMatthew G. Knepley   static PetscReal tri_v0[]   = {-1.0, -1.0,  0.0, -1.0,  -1.0, 0.0,  0.0, -1.0};
87*412e9a14SMatthew G. Knepley   static PetscReal tri_J[]    = {0.5, 0.0,
88*412e9a14SMatthew G. Knepley                                  0.0, 0.5,
89*412e9a14SMatthew G. Knepley 
90*412e9a14SMatthew G. Knepley                                  0.5, 0.0,
91*412e9a14SMatthew G. Knepley                                  0.0, 0.5,
92*412e9a14SMatthew G. Knepley 
93*412e9a14SMatthew G. Knepley                                  0.5, 0.0,
94*412e9a14SMatthew G. Knepley                                  0.0, 0.5,
95*412e9a14SMatthew G. Knepley 
96*412e9a14SMatthew G. Knepley                                  0.0, -0.5,
97*412e9a14SMatthew G. Knepley                                  0.5,  0.5};
98*412e9a14SMatthew G. Knepley   static PetscReal tri_invJ[] = {2.0, 0.0,
99*412e9a14SMatthew G. Knepley                                  0.0, 2.0,
100*412e9a14SMatthew G. Knepley 
101*412e9a14SMatthew G. Knepley                                  2.0, 0.0,
102*412e9a14SMatthew G. Knepley                                  0.0, 2.0,
103*412e9a14SMatthew G. Knepley 
104*412e9a14SMatthew G. Knepley                                  2.0, 0.0,
105*412e9a14SMatthew G. Knepley                                  0.0, 2.0,
106*412e9a14SMatthew G. Knepley 
107*412e9a14SMatthew G. Knepley                                  2.0,  2.0,
108*412e9a14SMatthew G. Knepley                                 -2.0,  0.0};
109260b6d3fSMatthew G. Knepley     /*
110260b6d3fSMatthew G. Knepley      3---------2---------2
111260b6d3fSMatthew G. Knepley      |         |         |
112260b6d3fSMatthew G. Knepley      |    D    2    C    |
113260b6d3fSMatthew G. Knepley      |         |         |
114260b6d3fSMatthew G. Knepley      3----3----0----1----1
115260b6d3fSMatthew G. Knepley      |         |         |
116260b6d3fSMatthew G. Knepley      |    A    0    B    |
117260b6d3fSMatthew G. Knepley      |         |         |
118260b6d3fSMatthew G. Knepley      0---------0---------1
119260b6d3fSMatthew G. Knepley      */
120*412e9a14SMatthew G. Knepley   static PetscReal quad_v0[]   = {-1.0, -1.0,  0.0, -1.0,  0.0, 0.0,  -1.0, 0.0};
121*412e9a14SMatthew G. Knepley   static PetscReal quad_J[]    = {0.5, 0.0,
122*412e9a14SMatthew G. Knepley                                   0.0, 0.5,
123*412e9a14SMatthew G. Knepley 
124*412e9a14SMatthew G. Knepley                                   0.5, 0.0,
125*412e9a14SMatthew G. Knepley                                   0.0, 0.5,
126*412e9a14SMatthew G. Knepley 
127*412e9a14SMatthew G. Knepley                                   0.5, 0.0,
128*412e9a14SMatthew G. Knepley                                   0.0, 0.5,
129*412e9a14SMatthew G. Knepley 
130*412e9a14SMatthew G. Knepley                                   0.5, 0.0,
131*412e9a14SMatthew G. Knepley                                   0.0, 0.5};
132*412e9a14SMatthew G. Knepley   static PetscReal quad_invJ[] = {2.0, 0.0,
133*412e9a14SMatthew G. Knepley                                   0.0, 2.0,
134*412e9a14SMatthew G. Knepley 
135*412e9a14SMatthew G. Knepley                                   2.0, 0.0,
136*412e9a14SMatthew G. Knepley                                   0.0, 2.0,
137*412e9a14SMatthew G. Knepley 
138*412e9a14SMatthew G. Knepley                                   2.0, 0.0,
139*412e9a14SMatthew G. Knepley                                   0.0, 2.0,
140*412e9a14SMatthew G. Knepley 
141*412e9a14SMatthew G. Knepley                                   2.0, 0.0,
142*412e9a14SMatthew G. Knepley                                   0.0, 2.0};
143c1879b55SMatthew G. Knepley     /*
144c1879b55SMatthew G. Knepley      Bottom (viewed from top)    Top
145c1879b55SMatthew G. Knepley      1---------2---------2       7---------2---------6
146c1879b55SMatthew G. Knepley      |         |         |       |         |         |
147c1879b55SMatthew G. Knepley      |    B    2    C    |       |    H    2    G    |
148c1879b55SMatthew G. Knepley      |         |         |       |         |         |
149c1879b55SMatthew G. Knepley      3----3----0----1----1       3----3----0----1----1
150c1879b55SMatthew G. Knepley      |         |         |       |         |         |
151c1879b55SMatthew G. Knepley      |    A    0    D    |       |    E    0    F    |
152c1879b55SMatthew G. Knepley      |         |         |       |         |         |
153c1879b55SMatthew G. Knepley      0---------0---------3       4---------0---------5
154c1879b55SMatthew G. Knepley      */
155*412e9a14SMatthew G. Knepley   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,
156*412e9a14SMatthew G. Knepley                                  -1.0, -1.0,  0.0,   0.0, -1.0,  0.0,  0.0, 0.0,  0.0,  -1.0,  0.0,  0.0};
157*412e9a14SMatthew G. Knepley   static PetscReal hex_J[]    = {0.5, 0.0, 0.0,
158*412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
159*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
160bed052eaSMatthew G. Knepley 
161*412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
162*412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
163*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
164*412e9a14SMatthew G. Knepley 
165*412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
166*412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
167*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
168*412e9a14SMatthew G. Knepley 
169*412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
170*412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
171*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
172*412e9a14SMatthew G. Knepley 
173*412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
174*412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
175*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
176*412e9a14SMatthew G. Knepley 
177*412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
178*412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
179*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
180*412e9a14SMatthew G. Knepley 
181*412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
182*412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
183*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
184*412e9a14SMatthew G. Knepley 
185*412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
186*412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
187*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5};
188*412e9a14SMatthew G. Knepley   static PetscReal hex_invJ[] = {2.0, 0.0, 0.0,
189*412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
190*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
191*412e9a14SMatthew G. Knepley 
192*412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
193*412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
194*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
195*412e9a14SMatthew G. Knepley 
196*412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
197*412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
198*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
199*412e9a14SMatthew G. Knepley 
200*412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
201*412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
202*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
203*412e9a14SMatthew G. Knepley 
204*412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
205*412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
206*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
207*412e9a14SMatthew G. Knepley 
208*412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
209*412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
210*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
211*412e9a14SMatthew G. Knepley 
212*412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
213*412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
214*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
215*412e9a14SMatthew G. Knepley 
216*412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
217*412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
218*412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0};
219bed052eaSMatthew G. Knepley 
220bed052eaSMatthew G. Knepley   PetscFunctionBegin;
221*412e9a14SMatthew G. Knepley   switch (ct) {
222*412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:      if (Nc) *Nc = 4; if (v0) *v0 = tri_v0;  if (J) *J = tri_J;  if (invJ) *invJ = tri_invJ;  break;
223*412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL: if (Nc) *Nc = 4; if (v0) *v0 = quad_v0; if (J) *J = quad_J; if (invJ) *invJ = quad_invJ; break;
224*412e9a14SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:    if (Nc) *Nc = 8; if (v0) *v0 = hex_v0;  if (J) *J = hex_J;  if (invJ) *invJ = hex_invJ;  break;
225*412e9a14SMatthew G. Knepley   default:
226*412e9a14SMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
227*412e9a14SMatthew G. Knepley   }
228bed052eaSMatthew G. Knepley   PetscFunctionReturn(0);
229bed052eaSMatthew G. Knepley }
230bed052eaSMatthew G. Knepley 
23180389061SMatthew G. Knepley /* Should this be here or in the DualSpace somehow? */
232*412e9a14SMatthew G. Knepley PetscErrorCode CellRefinerInCellTest_Internal(DMPolytopeType ct, const PetscReal point[], PetscBool *inside)
23380389061SMatthew G. Knepley {
23480389061SMatthew G. Knepley   PetscReal sum = 0.0;
23580389061SMatthew G. Knepley   PetscInt  d;
23680389061SMatthew G. Knepley 
23780389061SMatthew G. Knepley   PetscFunctionBegin;
23880389061SMatthew G. Knepley   *inside = PETSC_TRUE;
239*412e9a14SMatthew G. Knepley   switch (ct) {
240*412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
241*412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
242*412e9a14SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) {
24380389061SMatthew G. Knepley       if (point[d] < -1.0) {*inside = PETSC_FALSE; break;}
24480389061SMatthew G. Knepley       sum += point[d];
24580389061SMatthew G. Knepley     }
246*412e9a14SMatthew G. Knepley     if (sum > PETSC_SMALL) {*inside = PETSC_FALSE; break;}
24780389061SMatthew G. Knepley     break;
248*412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
249*412e9a14SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
250*412e9a14SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d)
251*412e9a14SMatthew G. Knepley       if (PetscAbsReal(point[d]) > 1.+PETSC_SMALL) {*inside = PETSC_FALSE; break;}
25294339e62SJed Brown     break;
25380389061SMatthew G. Knepley   default:
254*412e9a14SMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
25580389061SMatthew G. Knepley   }
25680389061SMatthew G. Knepley   PetscFunctionReturn(0);
25780389061SMatthew G. Knepley }
25880389061SMatthew G. Knepley 
259*412e9a14SMatthew G. Knepley /* Regular Refinment of Hybrid Meshes
26075d3a19aSMatthew G. Knepley 
261*412e9a14SMatthew G. Knepley    We would like to express regular refinement as a small set of rules that can be applied on every point of the Plex
262*412e9a14SMatthew G. Knepley    to automatically generate a refined Plex. In fact, we would like these rules to be general enough to encompass other
263*412e9a14SMatthew G. Knepley    transformations, such as changing from one type of cell to another, as simplex to hex.
26475d3a19aSMatthew G. Knepley 
265*412e9a14SMatthew G. Knepley    To start, we can create a function that takes an original cell type and returns the number of new cells replacing it
266*412e9a14SMatthew G. Knepley    and the types of the new cells.
267518a8359SMatthew G. Knepley 
268*412e9a14SMatthew G. Knepley    We need the group multiplication table for group actions from the dihedral group for each cell type.
26942525629SMatthew G. Knepley 
270*412e9a14SMatthew G. Knepley    We need an operator which takes in a cell, and produces a new set of cells with new faces and correct orientations. I think
271*412e9a14SMatthew G. Knepley    we can just write this operator for faces with identity, and then compose the face orientation actions to get the actual
272*412e9a14SMatthew G. Knepley    (face, orient) pairs for each subcell.
273*412e9a14SMatthew G. Knepley */
2740314a74cSLawrence Mitchell 
27575d3a19aSMatthew G. Knepley /*
276*412e9a14SMatthew G. Knepley   Input Parameters:
277*412e9a14SMatthew G. Knepley + ct - The type of the input cell
278*412e9a14SMatthew G. Knepley . co - The orientation of this cell in it parent
279*412e9a14SMatthew G. Knepley - cp - The requested cone point of this cell assuming orientation 0
280*412e9a14SMatthew G. Knepley 
281*412e9a14SMatthew G. Knepley   Output Parameters:
282*412e9a14SMatthew G. Knepley . cpnew - The new cone point, taking inout account the orientation co
283*412e9a14SMatthew G. Knepley */
284*412e9a14SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMPolytopeMapCell(DMPolytopeType ct, PetscInt co, PetscInt cp, PetscInt *cpnew)
285*412e9a14SMatthew G. Knepley {
286*412e9a14SMatthew G. Knepley   const PetscInt csize = DMPolytopeTypeGetConeSize(ct);
287*412e9a14SMatthew G. Knepley 
288*412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
289*412e9a14SMatthew G. Knepley   if (ct == DM_POLYTOPE_POINT) {*cpnew = cp;}
290*412e9a14SMatthew G. Knepley   else                         {*cpnew = (co < 0 ? -(co+1)-cp+csize : co+cp)%csize;}
291*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
292*412e9a14SMatthew G. Knepley }
293*412e9a14SMatthew G. Knepley 
294*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetCellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
295*412e9a14SMatthew G. Knepley {
296*412e9a14SMatthew G. Knepley   static PetscReal seg_v[]  = {-1.0,  0.0,  1.0};
297*412e9a14SMatthew G. Knepley   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};
298*412e9a14SMatthew G. Knepley   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};
299*412e9a14SMatthew G. Knepley   static PetscReal tet_v[]  = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
300*412e9a14SMatthew G. Knepley                                -1.0,  0.0, -1.0,   0.0,  0.0, -1.0,  -1.0,  1.0, -1.0,
301*412e9a14SMatthew G. Knepley                                -1.0, -1.0,  0.0,   0.0, -1.0,  0.0,  -1.0,  0.0,  0.0,  -1.0, -1.0,  1.0};
302*412e9a14SMatthew G. Knepley   static PetscReal hex_v[]  = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
303*412e9a14SMatthew G. Knepley                                -1.0,  0.0, -1.0,   0.0,  0.0, -1.0,   1.0,  0.0, -1.0,
304*412e9a14SMatthew G. Knepley                                -1.0,  1.0, -1.0,   0.0,  1.0, -1.0,   1.0,  1.0, -1.0,
305*412e9a14SMatthew G. Knepley                                -1.0, -1.0,  0.0,   0.0, -1.0,  0.0,   1.0, -1.0,  0.0,
306*412e9a14SMatthew G. Knepley                                -1.0,  0.0,  0.0,   0.0,  0.0,  0.0,   1.0,  0.0,  0.0,
307*412e9a14SMatthew G. Knepley                                -1.0,  1.0,  0.0,   0.0,  1.0,  0.0,   1.0,  1.0,  0.0,
308*412e9a14SMatthew G. Knepley                                -1.0, -1.0,  1.0,   0.0, -1.0,  1.0,   1.0, -1.0,  1.0,
309*412e9a14SMatthew G. Knepley                                -1.0,  0.0,  1.0,   0.0,  0.0,  1.0,   1.0,  0.0,  1.0,
310*412e9a14SMatthew G. Knepley                                -1.0,  1.0,  1.0,   0.0,  1.0,  1.0,   1.0,  1.0,  1.0};
311*412e9a14SMatthew G. Knepley 
312*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
313*412e9a14SMatthew G. Knepley   switch (ct) {
314*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:       *Nv =  3; *subcellV = seg_v;  break;
315*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:      *Nv =  6; *subcellV = tri_v;  break;
316*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL: *Nv =  9; *subcellV = quad_v; break;
317*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:   *Nv = 10; *subcellV = tet_v;  break;
318*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:    *Nv = 27; *subcellV = hex_v;  break;
319*412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
320*412e9a14SMatthew G. Knepley   }
321*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
322*412e9a14SMatthew G. Knepley }
323*412e9a14SMatthew G. Knepley 
324*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetCellVertices_ToHex(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
325*412e9a14SMatthew G. Knepley {
326*412e9a14SMatthew G. Knepley   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};
327*412e9a14SMatthew G. Knepley   static PetscReal tet_v[] = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
328*412e9a14SMatthew G. Knepley                               -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,
329*412e9a14SMatthew G. Knepley                               -1.0, -1.0,  0.0,  -1.0/3.0, -1.0, -1.0/3.0,   0.0, -1.0,  0.0,
330*412e9a14SMatthew G. Knepley                               -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,
331*412e9a14SMatthew G. Knepley                               -1.0, -1.0,  1.0,  -0.5, -0.5, -0.5};
332*412e9a14SMatthew G. Knepley   PetscErrorCode   ierr;
333*412e9a14SMatthew G. Knepley 
334*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
335*412e9a14SMatthew G. Knepley   switch (ct) {
336*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
337*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
338*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
339*412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerGetCellVertices_Regular(cr, ct, Nv, subcellV);CHKERRQ(ierr);break;
340*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:    *Nv =  7; *subcellV = tri_v; break;
341*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON: *Nv = 15; *subcellV = tet_v;  break;
342*412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
343*412e9a14SMatthew G. Knepley   }
344*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
345*412e9a14SMatthew G. Knepley }
346*412e9a14SMatthew G. Knepley 
347*412e9a14SMatthew G. Knepley /*
348*412e9a14SMatthew G. Knepley   DMPlexCellRefinerGetCellVertices - Get the set of refined vertices lying in the closure of a reference cell of given type
349*412e9a14SMatthew G. Knepley 
350*412e9a14SMatthew G. Knepley   Input Parameters:
351*412e9a14SMatthew G. Knepley + cr - The DMPlexCellRefiner object
352*412e9a14SMatthew G. Knepley - ct - The cell type
353*412e9a14SMatthew G. Knepley 
354*412e9a14SMatthew G. Knepley   Output Parameters:
355*412e9a14SMatthew G. Knepley + Nv       - The number of refined vertices in the closure of the reference cell of given type
356*412e9a14SMatthew G. Knepley - subcellV - The coordinates of these vertices in the reference cell
357*412e9a14SMatthew G. Knepley 
358*412e9a14SMatthew G. Knepley   Level: developer
359*412e9a14SMatthew G. Knepley 
360*412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerGetSubcellVertices()
361*412e9a14SMatthew G. Knepley */
362*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetCellVertices(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
363*412e9a14SMatthew G. Knepley {
364*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
365*412e9a14SMatthew G. Knepley 
366*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
367*412e9a14SMatthew G. Knepley   ierr = (*cr->ops->getcellvertices)(cr, ct, Nv, subcellV);CHKERRQ(ierr);
368*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
369*412e9a14SMatthew G. Knepley }
370*412e9a14SMatthew G. Knepley 
371*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetSubcellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
372*412e9a14SMatthew G. Knepley {
373*412e9a14SMatthew G. Knepley   static PetscInt seg_v[]  = {0, 1, 1, 2};
374*412e9a14SMatthew G. Knepley   static PetscInt tri_v[]  = {0, 3, 5,  3, 1, 4,  5, 4, 2,  3, 4, 5};
375*412e9a14SMatthew G. Knepley   static PetscInt quad_v[] = {0, 4, 8, 7,  4, 1, 5, 8,  8, 5, 2, 6,  7, 8, 6, 3};
376*412e9a14SMatthew G. Knepley   static PetscInt tet_v[]  = {0, 3, 1, 6,  3, 2, 4, 8,  1, 4, 5, 7,  6, 8, 7, 9,
377*412e9a14SMatthew G. Knepley                               1, 6, 3, 7,  8, 4, 3, 7,  7, 3, 1, 4,  7, 3, 8, 6};
378*412e9a14SMatthew G. Knepley   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,
379*412e9a14SMatthew G. Knepley                               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};
380*412e9a14SMatthew G. Knepley 
381*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
382*412e9a14SMatthew G. Knepley   if (ct != rct) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]);
383*412e9a14SMatthew G. Knepley   switch (ct) {
384*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:       *Nv = 2; *subcellV = &seg_v[r*(*Nv)];  break;
385*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:      *Nv = 3; *subcellV = &tri_v[r*(*Nv)];  break;
386*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL: *Nv = 4; *subcellV = &quad_v[r*(*Nv)]; break;
387*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:   *Nv = 4; *subcellV = &tet_v[r*(*Nv)];  break;
388*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:    *Nv = 8; *subcellV = &hex_v[r*(*Nv)];  break;
389*412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
390*412e9a14SMatthew G. Knepley   }
391*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
392*412e9a14SMatthew G. Knepley }
393*412e9a14SMatthew G. Knepley 
394*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetSubcellVertices_ToHex(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
395*412e9a14SMatthew G. Knepley {
396*412e9a14SMatthew G. Knepley   static PetscInt tri_v[]  = {0, 3, 6, 5,  3, 1, 4, 6,  5, 6, 4, 2};
397*412e9a14SMatthew G. Knepley   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};
398*412e9a14SMatthew G. Knepley   PetscErrorCode  ierr;
399*412e9a14SMatthew G. Knepley 
400*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
401*412e9a14SMatthew G. Knepley   switch (ct) {
402*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
403*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
404*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
405*412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerGetSubcellVertices_Regular(cr, ct, rct, r, Nv, subcellV);CHKERRQ(ierr);break;
406*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
407*412e9a14SMatthew G. Knepley       if (rct != DM_POLYTOPE_QUADRILATERAL) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]);
408*412e9a14SMatthew G. Knepley       *Nv = 4; *subcellV = &tri_v[r*(*Nv)]; break;
409*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
410*412e9a14SMatthew G. Knepley       if (rct != DM_POLYTOPE_HEXAHEDRON) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]);
411*412e9a14SMatthew G. Knepley       *Nv = 8; *subcellV = &tet_v[r*(*Nv)]; break;
412*412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
413*412e9a14SMatthew G. Knepley   }
414*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
415*412e9a14SMatthew G. Knepley }
416*412e9a14SMatthew G. Knepley 
417*412e9a14SMatthew G. Knepley /*
418*412e9a14SMatthew G. Knepley   DMPlexCellRefinerGetSubcellVertices - Get the set of refined vertices defining a subcell in the reference cell of given type
419*412e9a14SMatthew G. Knepley 
420*412e9a14SMatthew G. Knepley   Input Parameters:
421*412e9a14SMatthew G. Knepley + cr  - The DMPlexCellRefiner object
422*412e9a14SMatthew G. Knepley . ct  - The cell type
423*412e9a14SMatthew G. Knepley . rct - The type of subcell
424*412e9a14SMatthew G. Knepley - r   - The subcell index
425*412e9a14SMatthew G. Knepley 
426*412e9a14SMatthew G. Knepley   Output Parameters:
427*412e9a14SMatthew G. Knepley + Nv       - The number of refined vertices in the subcell
428*412e9a14SMatthew G. Knepley - subcellV - The indices of these vertices in the set of vertices returned by DMPlexCellRefinerGetCellVertices()
429*412e9a14SMatthew G. Knepley 
430*412e9a14SMatthew G. Knepley   Level: developer
431*412e9a14SMatthew G. Knepley 
432*412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerGetCellVertices()
433*412e9a14SMatthew G. Knepley */
434*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetSubcellVertices(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
435*412e9a14SMatthew G. Knepley {
436*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
437*412e9a14SMatthew G. Knepley 
438*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
439*412e9a14SMatthew G. Knepley   ierr = (*cr->ops->getsubcellvertices)(cr, ct, rct, r, Nv, subcellV);CHKERRQ(ierr);
440*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
441*412e9a14SMatthew G. Knepley }
442*412e9a14SMatthew G. Knepley 
443*412e9a14SMatthew G. Knepley /*
444*412e9a14SMatthew G. Knepley   Input Parameters:
445*412e9a14SMatthew G. Knepley + cr  - The DMPlexCellRefiner
446*412e9a14SMatthew G. Knepley . pct - The cell type of the parent, from whom the new cell is being produced
447*412e9a14SMatthew G. Knepley . po  - The orientation of the parent cell in its enclosing parent
448*412e9a14SMatthew G. Knepley . ct  - The type being produced
449*412e9a14SMatthew G. Knepley . r   - The replica number requested for the produced cell type
450*412e9a14SMatthew G. Knepley - o   - The relative orientation of the replica
451*412e9a14SMatthew G. Knepley 
452*412e9a14SMatthew G. Knepley   Output Parameters:
453*412e9a14SMatthew G. Knepley + rnew - The replica number, given the orientation of of the parent
454*412e9a14SMatthew G. Knepley - onew - The replica orientation, given the orientation of the parent
455*412e9a14SMatthew G. Knepley */
456*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
457*412e9a14SMatthew G. Knepley {
458*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
459*412e9a14SMatthew G. Knepley 
460*412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
461*412e9a14SMatthew G. Knepley   ierr = (*cr->ops->mapsubcells)(cr, pct, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
462*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
463*412e9a14SMatthew G. Knepley }
464*412e9a14SMatthew G. Knepley 
465*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells_Regular(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
466*412e9a14SMatthew G. Knepley {
467*412e9a14SMatthew G. Knepley   /* We shift any input orientation in order to make it non-negative
468*412e9a14SMatthew G. Knepley        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)
469*412e9a14SMatthew G. Knepley        The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po
470*412e9a14SMatthew G. Knepley        Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po
471*412e9a14SMatthew G. Knepley   */
472*412e9a14SMatthew G. Knepley   PetscInt tri_seg_o[] = {-2, 0,
473*412e9a14SMatthew G. Knepley                           -2, 0,
474*412e9a14SMatthew G. Knepley                           -2, 0,
475*412e9a14SMatthew G. Knepley                           0, -2,
476*412e9a14SMatthew G. Knepley                           0, -2,
477*412e9a14SMatthew G. Knepley                           0, -2};
478*412e9a14SMatthew G. Knepley   PetscInt tri_seg_r[] = {1, 0, 2,
479*412e9a14SMatthew G. Knepley                           0, 2, 1,
480*412e9a14SMatthew G. Knepley                           2, 1, 0,
481*412e9a14SMatthew G. Knepley                           0, 1, 2,
482*412e9a14SMatthew G. Knepley                           1, 2, 0,
483*412e9a14SMatthew G. Knepley                           2, 0, 1};
484*412e9a14SMatthew G. Knepley   PetscInt tri_tri_o[] = {0,  1,  2, -3, -2, -1,
485*412e9a14SMatthew G. Knepley                           2,  0,  1, -2, -1, -3,
486*412e9a14SMatthew G. Knepley                           1,  2,  0, -1, -3, -2,
487*412e9a14SMatthew G. Knepley                          -3, -2, -1,  0,  1,  2,
488*412e9a14SMatthew G. Knepley                          -1, -3, -2,  1,  2,  0,
489*412e9a14SMatthew G. Knepley                          -2, -1, -3,  2,  0,  1};
490*412e9a14SMatthew G. Knepley   /* orientation if the replica is the center triangle */
491*412e9a14SMatthew G. Knepley   PetscInt tri_tri_o_c[] = {2,  0,  1, -2, -1, -3,
492*412e9a14SMatthew G. Knepley                             1,  2,  0, -1, -3, -2,
493*412e9a14SMatthew G. Knepley                             0,  1,  2, -3, -2, -1,
494*412e9a14SMatthew G. Knepley                            -3, -2, -1,  0,  1,  2,
495*412e9a14SMatthew G. Knepley                            -1, -3, -2,  1,  2,  0,
496*412e9a14SMatthew G. Knepley                            -2, -1, -3,  2,  0,  1};
497*412e9a14SMatthew G. Knepley   PetscInt tri_tri_r[] = {0, 2, 1, 3,
498*412e9a14SMatthew G. Knepley                           2, 1, 0, 3,
499*412e9a14SMatthew G. Knepley                           1, 0, 2, 3,
500*412e9a14SMatthew G. Knepley                           0, 1, 2, 3,
501*412e9a14SMatthew G. Knepley                           1, 2, 0, 3,
502*412e9a14SMatthew G. Knepley                           2, 0, 1, 3};
503*412e9a14SMatthew G. Knepley   PetscInt quad_seg_r[] = {3, 2, 1, 0,
504*412e9a14SMatthew G. Knepley                            2, 1, 0, 3,
505*412e9a14SMatthew G. Knepley                            1, 0, 3, 2,
506*412e9a14SMatthew G. Knepley                            0, 3, 2, 1,
507*412e9a14SMatthew G. Knepley                            0, 1, 2, 3,
508*412e9a14SMatthew G. Knepley                            1, 2, 3, 0,
509*412e9a14SMatthew G. Knepley                            2, 3, 0, 1,
510*412e9a14SMatthew G. Knepley                            3, 0, 1, 2};
511*412e9a14SMatthew G. Knepley   PetscInt quad_quad_o[] = { 0,  1,  2,  3, -4, -3, -2, -1,
512*412e9a14SMatthew G. Knepley                              4,  0,  1,  2, -3, -2, -1, -4,
513*412e9a14SMatthew G. Knepley                              3,  4,  0,  1, -2, -1, -4, -3,
514*412e9a14SMatthew G. Knepley                              2,  3,  4,  0, -1, -4, -3, -2,
515*412e9a14SMatthew G. Knepley                             -4, -3, -2, -1,  0,  1,  2,  3,
516*412e9a14SMatthew G. Knepley                             -1, -4, -3, -2,  1,  2,  3,  0,
517*412e9a14SMatthew G. Knepley                             -2, -1, -4, -3,  2,  3,  0,  1,
518*412e9a14SMatthew G. Knepley                             -3, -2, -1, -4,  3,  0,  1,  2};
519*412e9a14SMatthew G. Knepley   PetscInt quad_quad_r[] = {0, 3, 2, 1,
520*412e9a14SMatthew G. Knepley                             3, 2, 1, 0,
521*412e9a14SMatthew G. Knepley                             2, 1, 0, 3,
522*412e9a14SMatthew G. Knepley                             1, 0, 3, 2,
523*412e9a14SMatthew G. Knepley                             0, 1, 2, 3,
524*412e9a14SMatthew G. Knepley                             1, 2, 3, 0,
525*412e9a14SMatthew G. Knepley                             2, 3, 0, 1,
526*412e9a14SMatthew G. Knepley                             3, 0, 1, 2};
527*412e9a14SMatthew G. Knepley   PetscInt tquad_tquad_o[] = { 0,  1, -2, -1,
528*412e9a14SMatthew G. Knepley                                1,  0, -1, -2,
529*412e9a14SMatthew G. Knepley                               -2, -1,  0,  1,
530*412e9a14SMatthew G. Knepley                               -1, -2,  1,  0};
531*412e9a14SMatthew G. Knepley   PetscInt tquad_tquad_r[] = {1, 0,
532*412e9a14SMatthew G. Knepley                               1, 0,
533*412e9a14SMatthew G. Knepley                               0, 1,
534*412e9a14SMatthew G. Knepley                               0, 1};
535*412e9a14SMatthew G. Knepley 
536*412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
537*412e9a14SMatthew G. Knepley   /* The default is no transformation */
538*412e9a14SMatthew G. Knepley   *rnew = r;
539*412e9a14SMatthew G. Knepley   *onew = o;
540*412e9a14SMatthew G. Knepley   switch (pct) {
541*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
542*412e9a14SMatthew G. Knepley       if (ct == DM_POLYTOPE_SEGMENT) {
543*412e9a14SMatthew G. Knepley         if      (po == 0 || po == -1) {*rnew = r;       *onew = o;}
544*412e9a14SMatthew G. Knepley         else if (po == 1 || po == -2) {*rnew = (r+1)%2; *onew = (o == 0 || o == -1) ? -2 : 0;}
545*412e9a14SMatthew G. Knepley         else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid orientation %D for segment", po);
546*412e9a14SMatthew G. Knepley       }
547*412e9a14SMatthew G. Knepley       break;
548*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
549*412e9a14SMatthew G. Knepley       switch (ct) {
550*412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
551*412e9a14SMatthew G. Knepley           if (o == -1) o = 0;
552*412e9a14SMatthew G. Knepley           if (o == -2) o = 1;
553*412e9a14SMatthew G. Knepley           *onew = tri_seg_o[(po+3)*2+o];
554*412e9a14SMatthew G. Knepley           *rnew = tri_seg_r[(po+3)*3+r];
555*412e9a14SMatthew G. Knepley           break;
556*412e9a14SMatthew G. Knepley         case DM_POLYTOPE_TRIANGLE:
557*412e9a14SMatthew G. Knepley           *onew = r == 3 && po < 0 ? tri_tri_o_c[((po+3)%3)*6+o+3] : tri_tri_o[(po+3)*6+o+3];
558*412e9a14SMatthew G. Knepley           *rnew = tri_tri_r[(po+3)*4+r];
559*412e9a14SMatthew G. Knepley           break;
560*412e9a14SMatthew G. Knepley         default: break;
561*412e9a14SMatthew G. Knepley       }
562*412e9a14SMatthew G. Knepley       break;
563*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
564*412e9a14SMatthew G. Knepley       switch (ct) {
565*412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
566*412e9a14SMatthew G. Knepley           *onew = o;
567*412e9a14SMatthew G. Knepley           *rnew = quad_seg_r[(po+4)*4+r];
568*412e9a14SMatthew G. Knepley           break;
569*412e9a14SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
570*412e9a14SMatthew G. Knepley           *onew = quad_quad_o[(po+4)*8+o+4];
571*412e9a14SMatthew G. Knepley           *rnew = quad_quad_r[(po+4)*4+r];
572*412e9a14SMatthew G. Knepley           break;
573*412e9a14SMatthew G. Knepley         default: break;
574*412e9a14SMatthew G. Knepley       }
575*412e9a14SMatthew G. Knepley       break;
576*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
577*412e9a14SMatthew G. Knepley       switch (ct) {
578*412e9a14SMatthew G. Knepley         /* DM_POLYTOPE_POINT_PRISM_TENSOR does not change */
579*412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEG_PRISM_TENSOR:
580*412e9a14SMatthew G. Knepley           *onew = tquad_tquad_o[(po+2)*4+o+2];
581*412e9a14SMatthew G. Knepley           *rnew = tquad_tquad_r[(po+2)*2+r];
582*412e9a14SMatthew G. Knepley           break;
583*412e9a14SMatthew G. Knepley         default: break;
584*412e9a14SMatthew G. Knepley       }
585*412e9a14SMatthew G. Knepley       break;
586*412e9a14SMatthew G. Knepley     default: break;
587*412e9a14SMatthew G. Knepley   }
588*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
589*412e9a14SMatthew G. Knepley }
590*412e9a14SMatthew G. Knepley 
591*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells_ToHex(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
592*412e9a14SMatthew G. Knepley {
593*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
594*412e9a14SMatthew G. Knepley   /* We shift any input orientation in order to make it non-negative
595*412e9a14SMatthew G. Knepley        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)
596*412e9a14SMatthew G. Knepley        The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po
597*412e9a14SMatthew G. Knepley        Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po
598*412e9a14SMatthew G. Knepley   */
599*412e9a14SMatthew G. Knepley   PetscInt tri_seg_o[] = {0, -2,
600*412e9a14SMatthew G. Knepley                           0, -2,
601*412e9a14SMatthew G. Knepley                           0, -2,
602*412e9a14SMatthew G. Knepley                           0, -2,
603*412e9a14SMatthew G. Knepley                           0, -2,
604*412e9a14SMatthew G. Knepley                           0, -2};
605*412e9a14SMatthew G. Knepley   PetscInt tri_seg_r[] = {2, 1, 0,
606*412e9a14SMatthew G. Knepley                           1, 0, 2,
607*412e9a14SMatthew G. Knepley                           0, 2, 1,
608*412e9a14SMatthew G. Knepley                           0, 1, 2,
609*412e9a14SMatthew G. Knepley                           1, 2, 0,
610*412e9a14SMatthew G. Knepley                           2, 0, 1};
611*412e9a14SMatthew G. Knepley   PetscInt tri_tri_o[] = {0,  1,  2,  3, -4, -3, -2, -1,
612*412e9a14SMatthew G. Knepley                           3,  0,  1,  2, -3, -2, -1, -4,
613*412e9a14SMatthew G. Knepley                           1,  2,  3,  0, -1, -4, -3, -2,
614*412e9a14SMatthew G. Knepley                          -4, -3, -2, -1,  0,  1,  2,  3,
615*412e9a14SMatthew G. Knepley                          -1, -4, -3, -2,  1,  2,  3,  0,
616*412e9a14SMatthew G. Knepley                          -3, -2, -1, -4,  3,  0,  1,  2};
617*412e9a14SMatthew G. Knepley   PetscInt tri_tri_r[] = {0, 2, 1,
618*412e9a14SMatthew G. Knepley                           2, 1, 0,
619*412e9a14SMatthew G. Knepley                           1, 0, 2,
620*412e9a14SMatthew G. Knepley                           0, 1, 2,
621*412e9a14SMatthew G. Knepley                           1, 2, 0,
622*412e9a14SMatthew G. Knepley                           2, 0, 1};
623*412e9a14SMatthew G. Knepley   PetscInt tquad_tquad_o[] = { 0,  1, -2, -1,
624*412e9a14SMatthew G. Knepley                                1,  0, -1, -2,
625*412e9a14SMatthew G. Knepley                               -2, -1,  0,  1,
626*412e9a14SMatthew G. Knepley                               -1, -2,  1,  0};
627*412e9a14SMatthew G. Knepley   PetscInt tquad_tquad_r[] = {1, 0,
628*412e9a14SMatthew G. Knepley                               1, 0,
629*412e9a14SMatthew G. Knepley                               0, 1,
630*412e9a14SMatthew G. Knepley                               0, 1};
631*412e9a14SMatthew G. Knepley   PetscInt tquad_quad_o[] = {-2, -1, -4, -3,  2,  3,  0,  1,
632*412e9a14SMatthew G. Knepley                               1,  2,  3,  0, -1, -4, -3, -2,
633*412e9a14SMatthew G. Knepley                              -4, -3, -2, -1,  0,  1,  2,  3,
634*412e9a14SMatthew G. Knepley                               1,  0,  3,  2, -3, -4, -1, -2};
635*412e9a14SMatthew G. Knepley 
636*412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
637*412e9a14SMatthew G. Knepley   *rnew = r;
638*412e9a14SMatthew G. Knepley   *onew = o;
639*412e9a14SMatthew G. Knepley   switch (pct) {
640*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
641*412e9a14SMatthew G. Knepley       switch (ct) {
642*412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
643*412e9a14SMatthew G. Knepley           if (o == -1) o = 0;
644*412e9a14SMatthew G. Knepley           if (o == -2) o = 1;
645*412e9a14SMatthew G. Knepley           *onew = tri_seg_o[(po+3)*2+o];
646*412e9a14SMatthew G. Knepley           *rnew = tri_seg_r[(po+3)*3+r];
647*412e9a14SMatthew G. Knepley           break;
648*412e9a14SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
649*412e9a14SMatthew G. Knepley           *onew = tri_tri_o[(po+3)*8+o+4];
650*412e9a14SMatthew G. Knepley           /* TODO See sheet, for fixing po == 1 and 2 */
651*412e9a14SMatthew G. Knepley           if (po ==  2 && r == 2 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+3)%4)+4];
652*412e9a14SMatthew G. Knepley           if (po ==  2 && r == 2 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+5)%4)];
653*412e9a14SMatthew G. Knepley           if (po ==  1 && r == 1 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+1)%4)+4];
654*412e9a14SMatthew G. Knepley           if (po ==  1 && r == 1 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+7)%4)];
655*412e9a14SMatthew G. Knepley           if (po == -1 && r == 2 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+3)%4)+4];
656*412e9a14SMatthew G. Knepley           if (po == -1 && r == 2 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+5)%4)];
657*412e9a14SMatthew G. Knepley           if (po == -2 && r == 1 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+1)%4)+4];
658*412e9a14SMatthew G. Knepley           if (po == -2 && r == 1 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+7)%4)];
659*412e9a14SMatthew G. Knepley           *rnew = tri_tri_r[(po+3)*3+r];
660*412e9a14SMatthew G. Knepley           break;
661*412e9a14SMatthew G. Knepley         default: break;
662*412e9a14SMatthew G. Knepley       }
663*412e9a14SMatthew G. Knepley       break;
664*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
665*412e9a14SMatthew G. Knepley       switch (ct) {
666*412e9a14SMatthew G. Knepley         /* DM_POLYTOPE_POINT_PRISM_TENSOR does not change */
667*412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEG_PRISM_TENSOR:
668*412e9a14SMatthew G. Knepley           *onew = tquad_tquad_o[(po+2)*4+o+2];
669*412e9a14SMatthew G. Knepley           *rnew = tquad_tquad_r[(po+2)*2+r];
670*412e9a14SMatthew G. Knepley           break;
671*412e9a14SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
672*412e9a14SMatthew G. Knepley           *onew = tquad_quad_o[(po+2)*8+o+4];
673*412e9a14SMatthew G. Knepley           *rnew = tquad_tquad_r[(po+2)*2+r];
674*412e9a14SMatthew G. Knepley           break;
675*412e9a14SMatthew G. Knepley         default: break;
676*412e9a14SMatthew G. Knepley       }
677*412e9a14SMatthew G. Knepley       break;
678*412e9a14SMatthew G. Knepley     default:
679*412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerMapSubcells_Regular(cr, pct, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
680*412e9a14SMatthew G. Knepley   }
681*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
682*412e9a14SMatthew G. Knepley }
683*412e9a14SMatthew G. Knepley 
684*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells_ToSimplex(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
685*412e9a14SMatthew G. Knepley {
686*412e9a14SMatthew G. Knepley   return DMPlexCellRefinerMapSubcells_Regular(cr, pct, po, ct, r, o, rnew, onew);
687*412e9a14SMatthew G. Knepley }
688*412e9a14SMatthew G. Knepley 
689*412e9a14SMatthew G. Knepley /*@
690*412e9a14SMatthew G. Knepley   DMPlexCellRefinerRefine - Return a description of the refinement for a given cell type
691*412e9a14SMatthew G. Knepley 
692*412e9a14SMatthew G. Knepley   Input Parameter:
693*412e9a14SMatthew G. Knepley . source - The cell type for a source point
694*412e9a14SMatthew G. Knepley 
695*412e9a14SMatthew G. Knepley   Output Parameter:
696*412e9a14SMatthew G. Knepley + Nt     - The number of cell types generated by refinement
697*412e9a14SMatthew G. Knepley . target - The cell types generated
698*412e9a14SMatthew G. Knepley . size   - The number of subcells of each type, ordered by dimension
699*412e9a14SMatthew G. Knepley . cone   - A list of the faces for each subcell of the same type as source
700*412e9a14SMatthew G. Knepley - ornt   - A list of the face orientations for each subcell of the same type as source
701*412e9a14SMatthew G. Knepley 
702*412e9a14SMatthew G. Knepley   Note: The cone array gives the cone of each subcell listed by the first three outputs. For the each cone point, we
703*412e9a14SMatthew G. Knepley   need the cell type, point identifier, and orientation within the subcell. The orientation is with respect to the canonical
704*412e9a14SMatthew G. Knepley   division (described in these outputs) of the cell in the original mesh. The point identifier is given by
705*412e9a14SMatthew G. Knepley $   the number of cones to be taken, or 0 for the current cell
706*412e9a14SMatthew G. Knepley $   the cell cone point number at each level from which it is subdivided
707*412e9a14SMatthew G. Knepley $   the replica number r of the subdivision.
708*412e9a14SMatthew G. Knepley   The orientation is with respect to the canonical cone orientation. For example, the prescription for edge division is
709*412e9a14SMatthew G. Knepley $   Nt     = 2
710*412e9a14SMatthew G. Knepley $   target = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT}
711*412e9a14SMatthew G. Knepley $   size   = {1, 2}
712*412e9a14SMatthew G. Knepley $   cone   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,  DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0}
713*412e9a14SMatthew G. Knepley $   ornt   = {                         0,                       0,                        0,                          0}
714*412e9a14SMatthew G. Knepley 
715*412e9a14SMatthew G. Knepley   Level: developer
716*412e9a14SMatthew G. Knepley 
717*412e9a14SMatthew G. Knepley .seealso: DMPlexRefineToHex()
718*412e9a14SMatthew G. Knepley @*/
719*412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerRefine(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
720*412e9a14SMatthew G. Knepley {
721*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
722*412e9a14SMatthew G. Knepley 
723*412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
724*412e9a14SMatthew G. Knepley   ierr = (*cr->ops->refine)(cr, source, Nt, target, size, cone, ornt);CHKERRQ(ierr);
725*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
726*412e9a14SMatthew G. Knepley }
727*412e9a14SMatthew G. Knepley 
728*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerRefine_Regular(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
729*412e9a14SMatthew G. Knepley {
730*412e9a14SMatthew G. Knepley   /* All vertices remain in the refined mesh */
731*412e9a14SMatthew G. Knepley   static DMPolytopeType vertexT[] = {DM_POLYTOPE_POINT};
732*412e9a14SMatthew G. Knepley   static PetscInt       vertexS[] = {1};
733*412e9a14SMatthew G. Knepley   static PetscInt       vertexC[] = {0};
734*412e9a14SMatthew G. Knepley   static PetscInt       vertexO[] = {0};
735*412e9a14SMatthew G. Knepley   /* Split all edges with a new vertex, making two new 2 edges
736*412e9a14SMatthew G. Knepley      0--0--0--1--1
737*412e9a14SMatthew G. Knepley   */
738*412e9a14SMatthew G. Knepley   static DMPolytopeType edgeT[]   = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT};
739*412e9a14SMatthew G. Knepley   static PetscInt       edgeS[]   = {1, 2};
740*412e9a14SMatthew G. Knepley   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};
741*412e9a14SMatthew G. Knepley   static PetscInt       edgeO[]   = {                         0,                       0,                        0,                          0};
742*412e9a14SMatthew G. Knepley   /* Do not split tensor edges */
743*412e9a14SMatthew G. Knepley   static DMPolytopeType tedgeT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR};
744*412e9a14SMatthew G. Knepley   static PetscInt       tedgeS[]  = {1};
745*412e9a14SMatthew G. Knepley   static PetscInt       tedgeC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
746*412e9a14SMatthew G. Knepley   static PetscInt       tedgeO[]  = {                         0,                          0};
747*412e9a14SMatthew G. Knepley   /* Add 3 edges inside every triangle, making 4 new triangles.
74875d3a19aSMatthew G. Knepley    2
74975d3a19aSMatthew G. Knepley    |\
75075d3a19aSMatthew G. Knepley    | \
75175d3a19aSMatthew G. Knepley    |  \
752*412e9a14SMatthew G. Knepley    0   1
75375d3a19aSMatthew G. Knepley    | C  \
75475d3a19aSMatthew G. Knepley    |     \
75575d3a19aSMatthew G. Knepley    |      \
75675d3a19aSMatthew G. Knepley    2---1---1
75775d3a19aSMatthew G. Knepley    |\  D  / \
758*412e9a14SMatthew G. Knepley    1 2   0   0
75975d3a19aSMatthew G. Knepley    |A \ /  B  \
760*412e9a14SMatthew G. Knepley    0-0-0---1---1
76175d3a19aSMatthew G. Knepley   */
762*412e9a14SMatthew G. Knepley   static DMPolytopeType triT[]    = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE};
763*412e9a14SMatthew G. Knepley   static PetscInt       triS[]    = {3, 4};
764*412e9a14SMatthew G. Knepley   static PetscInt       triC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
765*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 2, 0,
766*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 0, 0,
767*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1,
768*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0,
769*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0,
770*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2};
771*412e9a14SMatthew G. Knepley   static PetscInt       triO[]    = {0, 0,
772*412e9a14SMatthew G. Knepley                                      0, 0,
773*412e9a14SMatthew G. Knepley                                      0, 0,
774*412e9a14SMatthew G. Knepley                                      0, -2,  0,
775*412e9a14SMatthew G. Knepley                                      0,  0, -2,
776*412e9a14SMatthew G. Knepley                                     -2,  0,  0,
777*412e9a14SMatthew G. Knepley                                      0,  0,  0};
778*412e9a14SMatthew G. Knepley   /* Add a vertex in the center of each quadrilateral, and 4 edges inside, making 4 new quads.
779*412e9a14SMatthew G. Knepley      3----1----2----0----2
780*412e9a14SMatthew G. Knepley      |         |         |
781*412e9a14SMatthew G. Knepley      0    D    2    C    1
782*412e9a14SMatthew G. Knepley      |         |         |
783*412e9a14SMatthew G. Knepley      3----3----0----1----1
784*412e9a14SMatthew G. Knepley      |         |         |
785*412e9a14SMatthew G. Knepley      1    A    0    B    0
786*412e9a14SMatthew G. Knepley      |         |         |
787*412e9a14SMatthew G. Knepley      0----0----0----1----1
788*412e9a14SMatthew G. Knepley   */
789*412e9a14SMatthew G. Knepley   static DMPolytopeType quadT[]   = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
790*412e9a14SMatthew G. Knepley   static PetscInt       quadS[]   = {1, 4, 4};
791*412e9a14SMatthew G. Knepley   static PetscInt       quadC[]   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
792*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
793*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
794*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
795*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1,
796*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
797*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2,
798*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0};
799*412e9a14SMatthew G. Knepley   static PetscInt       quadO[]   = {0, 0,
800*412e9a14SMatthew G. Knepley                                      0, 0,
801*412e9a14SMatthew G. Knepley                                      0, 0,
802*412e9a14SMatthew G. Knepley                                      0, 0,
803*412e9a14SMatthew G. Knepley                                      0,  0, -2,  0,
804*412e9a14SMatthew G. Knepley                                      0,  0,  0, -2,
805*412e9a14SMatthew G. Knepley                                     -2,  0,  0,  0,
806*412e9a14SMatthew G. Knepley                                      0, -2,  0,  0};
807*412e9a14SMatthew G. Knepley   /* Add 1 edge inside every tensor quad, making 2 new tensor quads
808*412e9a14SMatthew G. Knepley      2----2----1----3----3
809*412e9a14SMatthew G. Knepley      |         |         |
810*412e9a14SMatthew G. Knepley      |         |         |
811*412e9a14SMatthew G. Knepley      |         |         |
812*412e9a14SMatthew G. Knepley      4    A    6    B    5
813*412e9a14SMatthew G. Knepley      |         |         |
814*412e9a14SMatthew G. Knepley      |         |         |
815*412e9a14SMatthew G. Knepley      |         |         |
816*412e9a14SMatthew G. Knepley      0----0----0----1----1
817*412e9a14SMatthew G. Knepley   */
818*412e9a14SMatthew G. Knepley   static DMPolytopeType tquadT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR};
819*412e9a14SMatthew G. Knepley   static PetscInt       tquadS[]  = {1, 2};
820*412e9a14SMatthew G. Knepley   static PetscInt       tquadC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
821*412e9a14SMatthew G. Knepley                                      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,
822*412e9a14SMatthew G. Knepley                                      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};
823*412e9a14SMatthew G. Knepley   static PetscInt       tquadO[]  = {0, 0,
824*412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
825*412e9a14SMatthew G. Knepley                                      0, 0, 0, 0};
826*412e9a14SMatthew G. Knepley   /* Add 1 edge and 8 triangles inside every cell, making 8 new tets
827*412e9a14SMatthew G. Knepley      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
828*412e9a14SMatthew G. Knepley      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]
829*412e9a14SMatthew G. Knepley      called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are
830*412e9a14SMatthew G. Knepley        [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3]
831*412e9a14SMatthew G. Knepley      The first four tets just cut off the corners, using the replica notation for new vertices,
832*412e9a14SMatthew G. Knepley        [v0,      (e0, 0), (e2, 0), (e3, 0)]
833*412e9a14SMatthew G. Knepley        [(e0, 0), v1,      (e1, 0), (e4, 0)]
834*412e9a14SMatthew G. Knepley        [(e2, 0), (e1, 0), v2,      (e5, 0)]
835*412e9a14SMatthew G. Knepley        [(e3, 0), (e4, 0), (e5, 0), v3     ]
836*412e9a14SMatthew G. Knepley      The next four tets match a vertex to the newly created faces from cutting off those first tets.
837*412e9a14SMatthew G. Knepley        [(e2, 0), (e3, 0), (e0, 0), (e5, 0)]
838*412e9a14SMatthew G. Knepley        [(e4, 0), (e1, 0), (e0, 0), (e5, 0)]
839*412e9a14SMatthew G. Knepley        [(e5, 0), (e0, 0), (e2, 0), (e1, 0)]
840*412e9a14SMatthew G. Knepley        [(e5, 0), (e0, 0), (e4, 0), (e3, 0)]
841*412e9a14SMatthew G. Knepley      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
842*412e9a14SMatthew G. Knepley        [(e2, 0), (e0, 0), (e3, 0)]
843*412e9a14SMatthew G. Knepley        [(e0, 0), (e1, 0), (e4, 0)]
844*412e9a14SMatthew G. Knepley        [(e2, 0), (e5, 0), (e1, 0)]
845*412e9a14SMatthew G. Knepley        [(e3, 0), (e4, 0), (e5, 0)]
846*412e9a14SMatthew G. Knepley      The next four, from the second group of tets, are
847*412e9a14SMatthew G. Knepley        [(e2, 0), (e0, 0), (e5, 0)]
848*412e9a14SMatthew G. Knepley        [(e4, 0), (e0, 0), (e5, 0)]
849*412e9a14SMatthew G. Knepley        [(e0, 0), (e1, 0), (e5, 0)]
850*412e9a14SMatthew G. Knepley        [(e5, 0), (e3, 0), (e0, 0)]
851*412e9a14SMatthew G. Knepley      I could write a program to generate these orientations by comparing the faces from GetRawFaces() with my existing table.
852*412e9a14SMatthew G. Knepley    */
853*412e9a14SMatthew G. Knepley   static DMPolytopeType tetT[]    = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_TETRAHEDRON};
854*412e9a14SMatthew G. Knepley   static PetscInt       tetS[]    = {1, 8, 8};
855*412e9a14SMatthew G. Knepley   static PetscInt       tetC[]    = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 2, 2, 1, 0,
856*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 2, 2,
857*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 1, 1,
858*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 1, 0, 1,
859*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 2, 1,
860*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 2, 0,
861*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 3, 1,
862*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    0,
863*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 0,    0,
864*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 0,    0,
865*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 1, 0, 1, DM_POLYTOPE_TRIANGLE, 1, 1, 2, DM_POLYTOPE_TRIANGLE, 0,    1, DM_POLYTOPE_TRIANGLE, 1, 3, 1,
866*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 1, 0, 2, DM_POLYTOPE_TRIANGLE, 0,    2, DM_POLYTOPE_TRIANGLE, 1, 2, 1, DM_POLYTOPE_TRIANGLE, 1, 3, 0,
867*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 0,    3, DM_POLYTOPE_TRIANGLE, 1, 1, 1, DM_POLYTOPE_TRIANGLE, 1, 2, 2, DM_POLYTOPE_TRIANGLE, 1, 3, 2,
868*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 0,    0, DM_POLYTOPE_TRIANGLE, 1, 2, 3, DM_POLYTOPE_TRIANGLE, 0,    4, DM_POLYTOPE_TRIANGLE, 0,    7,
869*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 0,    1, DM_POLYTOPE_TRIANGLE, 1, 3, 3, DM_POLYTOPE_TRIANGLE, 0,    5, DM_POLYTOPE_TRIANGLE, 0,    6,
870*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 0,    4, DM_POLYTOPE_TRIANGLE, 0,    6, DM_POLYTOPE_TRIANGLE, 0,    2, DM_POLYTOPE_TRIANGLE, 1, 0, 3,
871*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 0,    5, DM_POLYTOPE_TRIANGLE, 0,    7, DM_POLYTOPE_TRIANGLE, 0,    3, DM_POLYTOPE_TRIANGLE, 1, 1, 3};
872*412e9a14SMatthew G. Knepley   static PetscInt       tetO[]    = {0, 0,
873*412e9a14SMatthew G. Knepley                                      0,  0,  0,
874*412e9a14SMatthew G. Knepley                                      0,  0,  0,
875*412e9a14SMatthew G. Knepley                                      0,  0,  0,
876*412e9a14SMatthew G. Knepley                                      0,  0,  0,
877*412e9a14SMatthew G. Knepley                                      0,  0, -2,
878*412e9a14SMatthew G. Knepley                                      0,  0, -2,
879*412e9a14SMatthew G. Knepley                                      0, -2, -2,
880*412e9a14SMatthew G. Knepley                                      0, -2,  0,
881*412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,
882*412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,
883*412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,
884*412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,
885*412e9a14SMatthew G. Knepley                                     -3,  0,  0, -2,
886*412e9a14SMatthew G. Knepley                                     -2,  1,  0,  0,
887*412e9a14SMatthew G. Knepley                                     -2, -2, -1,  2,
888*412e9a14SMatthew G. Knepley                                     -2,  0, -2,  1};
889*412e9a14SMatthew G. Knepley   /* Add a vertex in the center of each cell, add 6 edges and 12 quads inside every cell, making 8 new hexes
890*412e9a14SMatthew G. Knepley      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
891*412e9a14SMatthew G. Knepley        [v0, v1, v2, v3] f0 bottom
892*412e9a14SMatthew G. Knepley        [v4, v5, v6, v7] f1 top
893*412e9a14SMatthew G. Knepley        [v0, v3, v5, v4] f2 front
894*412e9a14SMatthew G. Knepley        [v2, v1, v7, v6] f3 back
895*412e9a14SMatthew G. Knepley        [v3, v2, v6, v5] f4 right
896*412e9a14SMatthew G. Knepley        [v0, v4, v7, v1] f5 left
897*412e9a14SMatthew G. Knepley      The eight hexes are divided into four on the bottom, and four on the top,
898*412e9a14SMatthew G. Knepley        [v0,      (e0, 0),  (f0, 0),  (e3, 0),  (e9, 0), (f2, 0),  (c0, 0),  (f5, 0)]
899*412e9a14SMatthew G. Knepley        [(e0, 0), v1,       (e1, 0),  (f0, 0),  (f5, 0), (c0, 0),  (f3, 0),  (e10, 0)]
900*412e9a14SMatthew G. Knepley        [(f0, 0), (e1, 0),  v2,       (e2, 0),  (c0, 0), (f4, 0),  (e11, 0), (f3, 0)]
901*412e9a14SMatthew G. Knepley        [(e3, 0), (f0, 0),  (e2, 0),  v3,       (f2, 0), (e8, 0),  (f4, 0),  (c0, 0)]
902*412e9a14SMatthew G. Knepley        [(e9, 0), (f5, 0),  (c0, 0),  (f2, 0),  v4,      (e4, 0),  (f1, 0),  (e7, 0)]
903*412e9a14SMatthew G. Knepley        [(f2, 0), (c0, 0),  (f4, 0),  (e8, 0),  (e4, 0), v5,       (e5, 0),  (f1, 0)]
904*412e9a14SMatthew G. Knepley        [(c0, 0), (f3, 0),  (e11, 0), (f4, 0),  (f1, 0), (e5, 0),  v6,       (e6, 0)]
905*412e9a14SMatthew G. Knepley        [(f5, 0), (e10, 0), (f3, 0),  (c0, 0),  (e7, 0), (f1, 0),  (e6, 0),  v7]
906*412e9a14SMatthew G. Knepley      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,
907*412e9a14SMatthew G. Knepley        [(e9, 0), (f2, 0),  (c0, 0),  (f5, 0)]
908*412e9a14SMatthew G. Knepley        [(f5, 0), (c0, 0),  (f3, 0),  (e10, 0)]
909*412e9a14SMatthew G. Knepley        [(c0, 0), (f4, 0),  (e11, 0), (f3, 0)]
910*412e9a14SMatthew G. Knepley        [(f2, 0), (e8, 0),  (f4, 0),  (c0, 0)]
911*412e9a14SMatthew G. Knepley      and on the x-z plane,
912*412e9a14SMatthew G. Knepley        [(f0, 0), (e0, 0), (f5, 0), (c0, 0)]
913*412e9a14SMatthew G. Knepley        [(c0, 0), (f5, 0), (e7, 0), (f1, 0)]
914*412e9a14SMatthew G. Knepley        [(f4, 0), (c0, 0), (f1, 0), (e5, 0)]
915*412e9a14SMatthew G. Knepley        [(e2, 0), (f0, 0), (c0, 0), (f4, 0)]
916*412e9a14SMatthew G. Knepley      and on the y-z plane,
917*412e9a14SMatthew G. Knepley        [(e3, 0), (f2, 0), (c0, 0), (f0, 0)]
918*412e9a14SMatthew G. Knepley        [(f2, 0), (e4, 0), (f1, 0), (c0, 0)]
919*412e9a14SMatthew G. Knepley        [(c0, 0), (f1, 0), (e6, 0), (f3, 0)]
920*412e9a14SMatthew G. Knepley        [(f0, 0), (c0, 0), (f3, 0), (e1, 0)]
921*412e9a14SMatthew G. Knepley   */
922*412e9a14SMatthew G. Knepley   static DMPolytopeType hexT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
923*412e9a14SMatthew G. Knepley   static PetscInt       hexS[]    = {1, 6, 12, 8};
924*412e9a14SMatthew G. Knepley   static PetscInt       hexC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
925*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
926*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
927*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
928*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 0, 0,
929*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 5, 0, DM_POLYTOPE_POINT, 0, 0,
930*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 1, 5, 0,
931*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 5, 2,
932*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    3,
933*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    2,
934*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 5, 3, DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 0,    0,
935*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 1, 5, 1, DM_POLYTOPE_SEGMENT, 1, 1, 3, DM_POLYTOPE_SEGMENT, 0,    1,
936*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 4, 2,
937*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 0,
938*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 0, 3,
939*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2,
940*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    3,
941*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 0, 1,
942*412e9a14SMatthew G. Knepley                                      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,
943*412e9a14SMatthew G. Knepley                                      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,
944*412e9a14SMatthew G. Knepley                                      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,
945*412e9a14SMatthew G. Knepley                                      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,
946*412e9a14SMatthew G. Knepley                                      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,
947*412e9a14SMatthew G. Knepley                                      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,
948*412e9a14SMatthew G. Knepley                                      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,
949*412e9a14SMatthew G. Knepley                                      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};
950*412e9a14SMatthew G. Knepley   static PetscInt       hexO[]    = {0, 0,
951*412e9a14SMatthew G. Knepley                                      0, 0,
952*412e9a14SMatthew G. Knepley                                      0, 0,
953*412e9a14SMatthew G. Knepley                                      0, 0,
954*412e9a14SMatthew G. Knepley                                      0, 0,
955*412e9a14SMatthew G. Knepley                                      0, 0,
956*412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
957*412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
958*412e9a14SMatthew G. Knepley                                     -2, -2,  0,  0,
959*412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
960*412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
961*412e9a14SMatthew G. Knepley                                     -2, -2,  0,  0,
962*412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
963*412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
964*412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
965*412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
966*412e9a14SMatthew G. Knepley                                     -2, -2,  0,  0,
967*412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
968*412e9a14SMatthew G. Knepley                                      0, 0,  0, 0, -4, 0,
969*412e9a14SMatthew G. Knepley                                      0, 0, -1, 0, -4, 0,
970*412e9a14SMatthew G. Knepley                                      0, 0, -1, 0,  0, 0,
971*412e9a14SMatthew G. Knepley                                      0, 0,  0, 0,  0, 0,
972*412e9a14SMatthew G. Knepley                                     -4, 0,  0, 0, -4, 0,
973*412e9a14SMatthew G. Knepley                                     -4, 0,  0, 0,  0, 0,
974*412e9a14SMatthew G. Knepley                                     -4, 0, -1, 0,  0, 0,
975*412e9a14SMatthew G. Knepley                                     -4, 0, -1, 0, -4, 0};
976*412e9a14SMatthew G. Knepley   /* Add 3 quads inside every triangular prism, making 4 new prisms. */
977*412e9a14SMatthew G. Knepley   static DMPolytopeType tripT[]   = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_TRI_PRISM};
978*412e9a14SMatthew G. Knepley   static PetscInt       tripS[]   = {3, 4, 6, 8};
979*412e9a14SMatthew G. Knepley   static PetscInt       tripC[]   = {DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 3, 0,
980*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 1, 4, 0,
981*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 1, 2, 0,
982*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 4, 1,
983*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    0,
984*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3,
985*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2,
986*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 2, 0,
987*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 4, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 3, 0,
988*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 4, 0,
989*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 2,
990*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 4, 2, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 3, 2,
991*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 4, 2,
992*412e9a14SMatthew G. Knepley                                      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,
993*412e9a14SMatthew G. Knepley                                      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,
994*412e9a14SMatthew G. Knepley                                      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,
995*412e9a14SMatthew G. Knepley                                      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,
996*412e9a14SMatthew G. Knepley                                      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,
997*412e9a14SMatthew G. Knepley                                      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,
998*412e9a14SMatthew G. Knepley                                      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,
999*412e9a14SMatthew G. Knepley                                      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};
1000*412e9a14SMatthew G. Knepley   static PetscInt       tripO[]   = {0, 0,
1001*412e9a14SMatthew G. Knepley                                      0, 0,
1002*412e9a14SMatthew G. Knepley                                      0, 0,
1003*412e9a14SMatthew G. Knepley                                      0, -2, -2,
1004*412e9a14SMatthew G. Knepley                                     -2,  0, -2,
1005*412e9a14SMatthew G. Knepley                                     -2, -2,  0,
1006*412e9a14SMatthew G. Knepley                                      0,  0,  0,
1007*412e9a14SMatthew G. Knepley                                     -2,  0, -2, -2,
1008*412e9a14SMatthew G. Knepley                                     -2,  0, -2, -2,
1009*412e9a14SMatthew G. Knepley                                     -2,  0, -2, -2,
1010*412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1011*412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1012*412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1013*412e9a14SMatthew G. Knepley                                      0,  0,  0, -1,  0,
1014*412e9a14SMatthew G. Knepley                                      0,  0,  0,  0, -1,
1015*412e9a14SMatthew G. Knepley                                      0,  0, -1,  0,  0,
1016*412e9a14SMatthew G. Knepley                                      2,  0,  0,  0,  0,
1017*412e9a14SMatthew G. Knepley                                     -3,  0,  0, -1,  0,
1018*412e9a14SMatthew G. Knepley                                     -3,  0,  0,  0, -1,
1019*412e9a14SMatthew G. Knepley                                     -3,  0, -1,  0,  0,
1020*412e9a14SMatthew G. Knepley                                     -3,  0,  0,  0,  0};
1021*412e9a14SMatthew G. Knepley   /* Add 3 tensor quads inside every tensor triangular prism, making 4 new prisms.
1022*412e9a14SMatthew G. Knepley       2
1023*412e9a14SMatthew G. Knepley       |\
1024*412e9a14SMatthew G. Knepley       | \
1025*412e9a14SMatthew G. Knepley       |  \
1026*412e9a14SMatthew G. Knepley       0---1
102775d3a19aSMatthew G. Knepley 
1028*412e9a14SMatthew G. Knepley       2
102975d3a19aSMatthew G. Knepley 
1030*412e9a14SMatthew G. Knepley       0   1
103175d3a19aSMatthew G. Knepley 
1032*412e9a14SMatthew G. Knepley       2
1033*412e9a14SMatthew G. Knepley       |\
1034*412e9a14SMatthew G. Knepley       | \
1035*412e9a14SMatthew G. Knepley       |  \
1036*412e9a14SMatthew G. Knepley       0---1
1037*412e9a14SMatthew G. Knepley   */
1038*412e9a14SMatthew G. Knepley   static DMPolytopeType ttripT[]  = {DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_TRI_PRISM_TENSOR};
1039*412e9a14SMatthew G. Knepley   static PetscInt       ttripS[]  = {3, 4};
1040*412e9a14SMatthew G. Knepley   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,
1041*412e9a14SMatthew G. Knepley                                      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,
1042*412e9a14SMatthew G. Knepley                                      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,
1043*412e9a14SMatthew G. Knepley                                      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,
1044*412e9a14SMatthew G. Knepley                                      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,
1045*412e9a14SMatthew G. Knepley                                      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,
1046*412e9a14SMatthew G. Knepley                                      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};
1047*412e9a14SMatthew G. Knepley   static PetscInt       ttripO[]  = {0, 0, 0, 0,
1048*412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1049*412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1050*412e9a14SMatthew G. Knepley                                      0, 0,  0, -1,  0,
1051*412e9a14SMatthew G. Knepley                                      0, 0,  0,  0, -1,
1052*412e9a14SMatthew G. Knepley                                      0, 0, -1,  0,  0,
1053*412e9a14SMatthew G. Knepley                                      0, 0,  0,  0,  0};
1054*412e9a14SMatthew G. Knepley   /* Add 1 edge and 4 tensor quads inside every tensor quad prism, making 4 new prisms. */
1055*412e9a14SMatthew G. Knepley   static DMPolytopeType tquadpT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
1056*412e9a14SMatthew G. Knepley   static PetscInt       tquadpS[]  = {1, 4, 4};
1057*412e9a14SMatthew G. Knepley   static PetscInt       tquadpC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1058*412e9a14SMatthew G. Knepley                                       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,
1059*412e9a14SMatthew G. Knepley                                       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,
1060*412e9a14SMatthew G. Knepley                                       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,
1061*412e9a14SMatthew G. Knepley                                       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,
1062*412e9a14SMatthew G. Knepley                                       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,
1063*412e9a14SMatthew G. Knepley                                       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,
1064*412e9a14SMatthew G. Knepley                                       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,
1065*412e9a14SMatthew G. Knepley                                       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};
1066*412e9a14SMatthew G. Knepley   static PetscInt       tquadpO[]  = {0, 0,
1067*412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1068*412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1069*412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1070*412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1071*412e9a14SMatthew G. Knepley                                       0, 0,  0,  0, -1,  0,
1072*412e9a14SMatthew G. Knepley                                       0, 0,  0,  0,  0, -1,
1073*412e9a14SMatthew G. Knepley                                       0, 0, -1,  0,  0,  0,
1074*412e9a14SMatthew G. Knepley                                       0, 0,  0, -1,  0,  0};
107575d3a19aSMatthew G. Knepley 
1076*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1077*412e9a14SMatthew G. Knepley   switch (source) {
1078*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT:              *Nt = 1; *target = vertexT; *size = vertexS; *cone = vertexC; *ornt = vertexO; break;
1079*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:            *Nt = 2; *target = edgeT;   *size = edgeS;   *cone = edgeC;   *ornt = edgeO;   break;
1080*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT;  *size = tedgeS;  *cone = tedgeC;  *ornt = tedgeO;  break;
1081*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:           *Nt = 2; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1082*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:      *Nt = 3; *target = quadT;   *size = quadS;   *cone = quadC;   *ornt = quadO;   break;
1083*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:   *Nt = 2; *target = tquadT;  *size = tquadS;  *cone = tquadC;  *ornt = tquadO;  break;
1084*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:        *Nt = 3; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1085*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:         *Nt = 4; *target = hexT;    *size = hexS;    *cone = hexC;    *ornt = hexO;    break;
1086*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:          *Nt = 4; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
1087*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 2; *target = ttripT;  *size = ttripS;  *cone = ttripC;  *ornt = ttripO;  break;
1088*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:  *Nt = 3; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break;
1089*412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1090*412e9a14SMatthew G. Knepley   }
1091*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1092*412e9a14SMatthew G. Knepley }
109375d3a19aSMatthew G. Knepley 
1094*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerRefine_ToHex(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
1095*412e9a14SMatthew G. Knepley {
1096*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1097*412e9a14SMatthew G. Knepley   /* Change tensor edges to segments */
1098*412e9a14SMatthew G. Knepley   static DMPolytopeType tedgeT[]  = {DM_POLYTOPE_SEGMENT};
1099*412e9a14SMatthew G. Knepley   static PetscInt       tedgeS[]  = {1};
1100*412e9a14SMatthew G. Knepley   static PetscInt       tedgeC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
1101*412e9a14SMatthew G. Knepley   static PetscInt       tedgeO[]  = {                         0,                          0};
1102*412e9a14SMatthew G. Knepley   /* Add 1 vertex, 3 edges inside every triangle, making 3 new quadrilaterals.
1103e5337592SStefano Zampini    2
1104e5337592SStefano Zampini    |\
1105e5337592SStefano Zampini    | \
1106e5337592SStefano Zampini    |  \
1107e5337592SStefano Zampini    |   \
1108*412e9a14SMatthew G. Knepley    0    1
1109*412e9a14SMatthew G. Knepley    |     \
1110e5337592SStefano Zampini    |      \
1111e5337592SStefano Zampini    2       1
1112e5337592SStefano Zampini    |\     / \
1113e5337592SStefano Zampini    | 2   1   \
1114e5337592SStefano Zampini    |  \ /     \
1115*412e9a14SMatthew G. Knepley    1   |       0
1116e5337592SStefano Zampini    |   0        \
1117e5337592SStefano Zampini    |   |         \
1118*412e9a14SMatthew G. Knepley    |   |          \
1119*412e9a14SMatthew G. Knepley    0-0-0-----1-----1
1120e5337592SStefano Zampini   */
1121*412e9a14SMatthew G. Knepley   static DMPolytopeType triT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
1122*412e9a14SMatthew G. Knepley   static PetscInt       triS[]    = {1, 3, 3};
1123*412e9a14SMatthew G. Knepley   static PetscInt       triC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0,    0,
1124*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0,    0,
1125*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0,    0,
1126*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1,
1127*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
1128*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0};
1129*412e9a14SMatthew G. Knepley   static PetscInt       triO[]    = {0, 0,
1130*412e9a14SMatthew G. Knepley                                      0, 0,
1131*412e9a14SMatthew G. Knepley                                      0, 0,
1132*412e9a14SMatthew G. Knepley                                      0,  0, -2,  0,
1133*412e9a14SMatthew G. Knepley                                      0,  0,  0, -2,
1134*412e9a14SMatthew G. Knepley                                      0, -2,  0,  0};
1135*412e9a14SMatthew G. Knepley   /* Add 1 edge inside every tensor quad, making 2 new quadrilaterals
1136*412e9a14SMatthew G. Knepley      2----2----1----3----3
11374330a3fcSStefano Zampini      |         |         |
11384330a3fcSStefano Zampini      |         |         |
11394330a3fcSStefano Zampini      |         |         |
1140*412e9a14SMatthew G. Knepley      4    A    6    B    5
11414330a3fcSStefano Zampini      |         |         |
1142*412e9a14SMatthew G. Knepley      |         |         |
1143*412e9a14SMatthew G. Knepley      |         |         |
1144*412e9a14SMatthew G. Knepley      0----0----0----1----1
11454330a3fcSStefano Zampini   */
1146*412e9a14SMatthew G. Knepley   static DMPolytopeType tquadT[]  = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
1147*412e9a14SMatthew G. Knepley   static PetscInt       tquadS[]  = {1, 2};
1148*412e9a14SMatthew G. Knepley   static PetscInt       tquadC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1149*412e9a14SMatthew G. Knepley                                      /* TODO  Fix these */
1150*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1151*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0,    0};
1152*412e9a14SMatthew G. Knepley   static PetscInt       tquadO[]  = {0, 0,
1153*412e9a14SMatthew G. Knepley                                      0, 0, -2, -2,
1154*412e9a14SMatthew G. Knepley                                      0, 0, -2, -2};
1155*412e9a14SMatthew G. Knepley   /* Add 6 triangles inside every cell, making 4 new hexs
1156*412e9a14SMatthew G. Knepley      TODO: Need different SubcellMap(). Need to make a struct with the function pointers in it
1157*412e9a14SMatthew G. Knepley      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
1158*412e9a14SMatthew G. Knepley      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]
1159*412e9a14SMatthew G. Knepley      called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are
1160*412e9a14SMatthew G. Knepley        [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3]
1161*412e9a14SMatthew G. Knepley      We make a new hex in each corner
1162*412e9a14SMatthew G. Knepley        [v0, (e0, 0), (f0, 0), (e2, 0), (e3, 0), (f2, 0), (c0, 0), (f1, 0)]
1163*412e9a14SMatthew G. Knepley        [v1, (e4, 0), (f3, 0), (e1, 0), (e0, 0), (f0, 0), (c0, 0), (f1, 0)]
1164*412e9a14SMatthew G. Knepley        [v2, (e1, 0), (f3, 0), (e5, 0), (e2, 0), (f2, 0), (c0, 0), (f0, 0)]
1165*412e9a14SMatthew G. Knepley        [v3, (e4, 0), (f1, 0), (e3, 0), (e5, 0), (f2, 0), (c0, 0), (f3, 0)]
1166*412e9a14SMatthew G. Knepley      We create a new face for each edge
1167*412e9a14SMatthew G. Knepley        [(e3, 0), (f2, 0), (c0, 0), (f1, 0)]
1168*412e9a14SMatthew G. Knepley        [(f0, 0), (e0, 0), (f1, 0), (c0, 0)]
1169*412e9a14SMatthew G. Knepley        [(e2, 0), (f0, 0), (c0, 0), (f2, 0)]
1170*412e9a14SMatthew G. Knepley        [(f3, 0), (e4, 0), (f1, 0), (c0, 0)]
1171*412e9a14SMatthew G. Knepley        [(e1, 0), (f3, 0), (c0, 0), (f0, 0)]
1172*412e9a14SMatthew G. Knepley        [(e5, 0), (f3, 0), (c0, 0), (f2, 0)]
1173*412e9a14SMatthew G. Knepley      I could write a program to generate these from the first hex by acting with the symmetry group to take one subcell into another.
117475d3a19aSMatthew G. Knepley    */
1175*412e9a14SMatthew G. Knepley   static DMPolytopeType tetT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1176*412e9a14SMatthew G. Knepley   static PetscInt       tetS[]    = {1, 4, 6, 4};
1177*412e9a14SMatthew G. Knepley   static PetscInt       tetC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1178*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
1179*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
1180*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
1181*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 0,
1182*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
1183*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1184*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    3,
1185*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 0, 1,
1186*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1,
1187*412e9a14SMatthew G. Knepley                                      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,
1188*412e9a14SMatthew G. Knepley                                      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,
1189*412e9a14SMatthew G. Knepley                                      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,
1190*412e9a14SMatthew G. Knepley                                      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};
1191*412e9a14SMatthew G. Knepley   static PetscInt       tetO[]    = {0, 0,
1192*412e9a14SMatthew G. Knepley                                      0, 0,
1193*412e9a14SMatthew G. Knepley                                      0, 0,
1194*412e9a14SMatthew G. Knepley                                      0, 0,
1195*412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1196*412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
1197*412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1198*412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
1199*412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1200*412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1201*412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,  0,  0,
1202*412e9a14SMatthew G. Knepley                                      1, -1,  1,  0,  0,  3,
1203*412e9a14SMatthew G. Knepley                                      0, -4,  1, -1,  0,  3,
1204*412e9a14SMatthew G. Knepley                                      1, -4,  3, -2, -4,  3};
1205*412e9a14SMatthew G. Knepley   /* Add 3 quads inside every triangular prism, making 4 new prisms. */
1206*412e9a14SMatthew G. Knepley   static DMPolytopeType tripT[]   = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1207*412e9a14SMatthew G. Knepley   static PetscInt       tripS[]   = {1, 5, 9, 6};
1208*412e9a14SMatthew G. Knepley   static PetscInt       tripC[]   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1209*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
1210*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
1211*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
1212*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 0, 0,
1213*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 1,
1214*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    2,
1215*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3,
1216*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1217*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 0,
1218*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 0,
1219*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 2,
1220*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 3, 2,
1221*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 4, 2,
1222*412e9a14SMatthew G. Knepley                                      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,
1223*412e9a14SMatthew G. Knepley                                      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,
1224*412e9a14SMatthew G. Knepley                                      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,
1225*412e9a14SMatthew G. Knepley                                      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,
1226*412e9a14SMatthew G. Knepley                                      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,
1227*412e9a14SMatthew G. Knepley                                      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};
1228*412e9a14SMatthew G. Knepley   static PetscInt       tripO[]   = {0, 0,
1229*412e9a14SMatthew G. Knepley                                      0, 0,
1230*412e9a14SMatthew G. Knepley                                      0, 0,
1231*412e9a14SMatthew G. Knepley                                      0, 0,
1232*412e9a14SMatthew G. Knepley                                      0, 0,
1233*412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1234*412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
1235*412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1236*412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1237*412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1238*412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1239*412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1240*412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1241*412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1242*412e9a14SMatthew G. Knepley                                      0,  0,  0, -1,  0,  1,
1243*412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,  0, -4,
1244*412e9a14SMatthew G. Knepley                                      0,  0,  0,  0, -1,  1,
1245*412e9a14SMatthew G. Knepley                                     -4,  0,  0, -1,  0,  1,
1246*412e9a14SMatthew G. Knepley                                     -4,  0,  0,  0,  0, -4,
1247*412e9a14SMatthew G. Knepley                                     -4,  0,  0,  0, -1,  1};
1248*412e9a14SMatthew G. Knepley   /* Add 3 tensor quads inside every tensor triangular prism, making 4 new tensor triangular prisms.
1249*412e9a14SMatthew G. Knepley       2
1250*412e9a14SMatthew G. Knepley       |\
1251*412e9a14SMatthew G. Knepley       | \
1252*412e9a14SMatthew G. Knepley       |  \
1253*412e9a14SMatthew G. Knepley       0---1
125475d3a19aSMatthew G. Knepley 
1255*412e9a14SMatthew G. Knepley       2
125675d3a19aSMatthew G. Knepley 
1257*412e9a14SMatthew G. Knepley       0   1
125875d3a19aSMatthew G. Knepley 
1259*412e9a14SMatthew G. Knepley       2
1260*412e9a14SMatthew G. Knepley       |\
1261*412e9a14SMatthew G. Knepley       | \
1262*412e9a14SMatthew G. Knepley       |  \
1263*412e9a14SMatthew G. Knepley       0---1
126475d3a19aSMatthew G. Knepley   */
1265*412e9a14SMatthew G. Knepley   static DMPolytopeType ttripT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
1266*412e9a14SMatthew G. Knepley   static PetscInt       ttripS[]  = {1, 3, 3};
1267*412e9a14SMatthew G. Knepley   static PetscInt       ttripC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1268*412e9a14SMatthew G. Knepley                                      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,
1269*412e9a14SMatthew G. Knepley                                      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,
1270*412e9a14SMatthew G. Knepley                                      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,
1271*412e9a14SMatthew G. Knepley                                      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,
1272*412e9a14SMatthew G. Knepley                                      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,
1273*412e9a14SMatthew G. Knepley                                      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};
1274*412e9a14SMatthew G. Knepley   static PetscInt       ttripO[]  = {0, 0,
1275*412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1276*412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1277*412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1278*412e9a14SMatthew G. Knepley                                      0, 0, 0,  0, -1, 0,
1279*412e9a14SMatthew G. Knepley                                      0, 0, 0,  0,  0, -1,
1280*412e9a14SMatthew G. Knepley                                      0, 0, 0, -1,  0, 0};
1281*412e9a14SMatthew G. Knepley   /* TODO Add 3 quads inside every tensor triangular prism, making 4 new triangular prisms.
1282*412e9a14SMatthew G. Knepley       2
1283*412e9a14SMatthew G. Knepley       |\
1284*412e9a14SMatthew G. Knepley       | \
1285*412e9a14SMatthew G. Knepley       |  \
1286*412e9a14SMatthew G. Knepley       0---1
128775d3a19aSMatthew G. Knepley 
1288*412e9a14SMatthew G. Knepley       2
128975d3a19aSMatthew G. Knepley 
1290*412e9a14SMatthew G. Knepley       0   1
129175d3a19aSMatthew G. Knepley 
1292*412e9a14SMatthew G. Knepley       2
1293*412e9a14SMatthew G. Knepley       |\
1294*412e9a14SMatthew G. Knepley       | \
1295*412e9a14SMatthew G. Knepley       |  \
1296*412e9a14SMatthew G. Knepley       0---1
1297a97b51b8SMatthew G. Knepley   */
1298*412e9a14SMatthew G. Knepley   static DMPolytopeType ctripT[]  = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1299*412e9a14SMatthew G. Knepley   static PetscInt       ctripS[]  = {1, 3, 3};
1300*412e9a14SMatthew G. Knepley   static PetscInt       ctripC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1301*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1302*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0,
1303*412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 4, 0,
1304*412e9a14SMatthew G. Knepley                                      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,
1305*412e9a14SMatthew G. Knepley                                      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,
1306*412e9a14SMatthew G. Knepley                                      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};
1307*412e9a14SMatthew G. Knepley   static PetscInt       ctripO[]  = {0, 0,
1308*412e9a14SMatthew G. Knepley                                      0, 0, -2, -2,
1309*412e9a14SMatthew G. Knepley                                      0, 0, -2, -2,
1310*412e9a14SMatthew G. Knepley                                      0, 0, -2, -2,
1311*412e9a14SMatthew G. Knepley                                     -4, 0, 0, -1,  0,  1,
1312*412e9a14SMatthew G. Knepley                                     -4, 0, 0,  0,  0, -4,
1313*412e9a14SMatthew G. Knepley                                     -4, 0, 0,  0, -1,  1};
1314*412e9a14SMatthew G. Knepley   /* Add 1 edge and 4 quads inside every tensor quad prism, making 4 new hexahedra. */
1315*412e9a14SMatthew G. Knepley   static DMPolytopeType tquadpT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
1316*412e9a14SMatthew G. Knepley   static PetscInt       tquadpS[]  = {1, 4, 4};
1317*412e9a14SMatthew G. Knepley   static PetscInt       tquadpC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1318*412e9a14SMatthew G. Knepley                                       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,
1319*412e9a14SMatthew G. Knepley                                       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,
1320*412e9a14SMatthew G. Knepley                                       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,
1321*412e9a14SMatthew G. Knepley                                       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,
1322*412e9a14SMatthew G. Knepley                                       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,
1323*412e9a14SMatthew G. Knepley                                       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,
1324*412e9a14SMatthew G. Knepley                                       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,
1325*412e9a14SMatthew G. Knepley                                       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};
1326*412e9a14SMatthew G. Knepley   static PetscInt       tquadpO[]  = {0, 0,
1327*412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1328*412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1329*412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1330*412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1331*412e9a14SMatthew G. Knepley                                       0, 0,  0,  0, -1,  0,
1332*412e9a14SMatthew G. Knepley                                       0, 0,  0,  0,  0, -1,
1333*412e9a14SMatthew G. Knepley                                       0, 0, -1,  0,  0,  0,
1334*412e9a14SMatthew G. Knepley                                       0, 0,  0, -1,  0,  0};
1335*412e9a14SMatthew G. Knepley   PetscBool convertTensor = PETSC_TRUE;
1336a97b51b8SMatthew G. Knepley 
1337*412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
1338*412e9a14SMatthew G. Knepley   if (convertTensor) {
1339*412e9a14SMatthew G. Knepley     switch (source) {
1340*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_POINT:
1341*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
1342*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
1343*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:
1344*412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine_Regular(cr, source, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1345a97b51b8SMatthew G. Knepley         break;
1346*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT;  *size = tedgeS;  *cone = tedgeC;  *ornt = tedgeO;  break;
1347*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:   *Nt = 2; *target = tquadT;  *size = tquadS;  *cone = tquadC;  *ornt = tquadO;  break;
1348*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 3; *target = ctripT;  *size = ctripS;  *cone = ctripC;  *ornt = ctripO;  break;
1349*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:  *Nt = 3; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break;
1350*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:           *Nt = 3; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1351*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:        *Nt = 4; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1352*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM:          *Nt = 4; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
1353*412e9a14SMatthew G. Knepley       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1354b5da9499SMatthew G. Knepley     }
1355b5da9499SMatthew G. Knepley   } else {
1356*412e9a14SMatthew G. Knepley     switch (source) {
1357*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_POINT:
1358*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_POINT_PRISM_TENSOR:
1359*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
1360*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
1361*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:
1362*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:
1363*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
1364*412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine_Regular(cr, source, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1365b5da9499SMatthew G. Knepley         break;
1366*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:           *Nt = 3; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1367*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:        *Nt = 4; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1368*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM:          *Nt = 4; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
1369*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 3; *target = ttripT;  *size = ttripS;  *cone = ttripC;  *ornt = ttripO;  break;
1370*412e9a14SMatthew G. Knepley       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
137127fcede3SMatthew G. Knepley     }
137275d3a19aSMatthew G. Knepley   }
137375d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
137475d3a19aSMatthew G. Knepley }
137575d3a19aSMatthew G. Knepley 
1376*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerRefine_ToSimplex(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
137775d3a19aSMatthew G. Knepley {
1378*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1379*412e9a14SMatthew G. Knepley 
1380*412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
1381*412e9a14SMatthew G. Knepley   switch (source) {
1382*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT:
1383*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
1384*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
1385*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
1386*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
1387*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
1388*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
1389*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
1390*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
1391*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
1392*412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
1393*412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine_Regular(cr, source, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1394*412e9a14SMatthew G. Knepley       break;
1395*412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1396*412e9a14SMatthew G. Knepley   }
1397*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1398*412e9a14SMatthew G. Knepley }
1399*412e9a14SMatthew G. Knepley 
1400*412e9a14SMatthew G. Knepley static PetscErrorCode CellRefinerCreateOffset_Internal(DMPlexCellRefiner cr, PetscInt ctOrder[], PetscInt ctStart[], PetscInt **offset)
1401*412e9a14SMatthew G. Knepley {
1402*412e9a14SMatthew G. Knepley   PetscInt       c, cN, *off;
140375d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
140475d3a19aSMatthew G. Knepley 
140575d3a19aSMatthew G. Knepley   PetscFunctionBegin;
1406*412e9a14SMatthew G. Knepley   ierr = PetscCalloc1(DM_NUM_POLYTOPES*DM_NUM_POLYTOPES, &off);CHKERRQ(ierr);
1407*412e9a14SMatthew G. Knepley   for (c = DM_POLYTOPE_POINT; c < DM_NUM_POLYTOPES; ++c) {
1408*412e9a14SMatthew G. Knepley     const DMPolytopeType ct = (DMPolytopeType) c;
1409*412e9a14SMatthew G. Knepley     for (cN = DM_POLYTOPE_POINT; cN < DM_NUM_POLYTOPES; ++cN) {
1410*412e9a14SMatthew G. Knepley       const DMPolytopeType ctNew = (DMPolytopeType) cN;
1411*412e9a14SMatthew G. Knepley       DMPolytopeType      *rct;
1412*412e9a14SMatthew G. Knepley       PetscInt            *rsize, *cone, *ornt;
1413*412e9a14SMatthew G. Knepley       PetscInt             Nct, n, i;
1414*412e9a14SMatthew G. Knepley 
1415*412e9a14SMatthew G. Knepley       if (DMPolytopeTypeGetDim(ct) < 0 || DMPolytopeTypeGetDim(ctNew) < 0) {off[ct*DM_NUM_POLYTOPES+ctNew] = -1; break;}
1416*412e9a14SMatthew G. Knepley       off[ct*DM_NUM_POLYTOPES+ctNew] = 0;
1417*412e9a14SMatthew G. Knepley       for (i = DM_POLYTOPE_POINT; i < DM_NUM_POLYTOPES; ++i) {
1418*412e9a14SMatthew G. Knepley         const DMPolytopeType ict  = (DMPolytopeType) ctOrder[i];
1419*412e9a14SMatthew G. Knepley         const DMPolytopeType ictn = (DMPolytopeType) ctOrder[i+1];
1420*412e9a14SMatthew G. Knepley 
1421*412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine(cr, ict, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
1422*412e9a14SMatthew G. Knepley         if (ict == ct) {
1423*412e9a14SMatthew G. Knepley           for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) break;
1424*412e9a14SMatthew G. Knepley           if (n == Nct) off[ct*DM_NUM_POLYTOPES+ctNew] = -1;
1425*412e9a14SMatthew G. Knepley           break;
1426*412e9a14SMatthew G. Knepley         }
1427*412e9a14SMatthew G. Knepley         for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) off[ct*DM_NUM_POLYTOPES+ctNew] += (ctStart[ictn]-ctStart[ict]) * rsize[n];
1428*412e9a14SMatthew G. Knepley       }
1429*412e9a14SMatthew G. Knepley     }
1430*412e9a14SMatthew G. Knepley   }
1431*412e9a14SMatthew G. Knepley   *offset = off;
1432*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1433*412e9a14SMatthew G. Knepley }
1434*412e9a14SMatthew G. Knepley 
1435*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerSetStarts(DMPlexCellRefiner cr, const PetscInt ctStart[], const PetscInt ctStartNew[])
1436*412e9a14SMatthew G. Knepley {
1437*412e9a14SMatthew G. Knepley   const PetscInt ctSize = DM_NUM_POLYTOPES+1;
1438*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1439*412e9a14SMatthew G. Knepley 
1440*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1441*412e9a14SMatthew G. Knepley   if (cr->setupcalled) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_ARG_WRONGSTATE, "Must call this function before DMPlexCellRefinerSetUp()");
1442*412e9a14SMatthew G. Knepley   ierr = PetscCalloc2(ctSize, &cr->ctStart, ctSize, &cr->ctStartNew);CHKERRQ(ierr);
1443*412e9a14SMatthew G. Knepley   ierr = PetscArraycpy(cr->ctStart,    ctStart,    ctSize);CHKERRQ(ierr);
1444*412e9a14SMatthew G. Knepley   ierr = PetscArraycpy(cr->ctStartNew, ctStartNew, ctSize);CHKERRQ(ierr);
1445*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1446*412e9a14SMatthew G. Knepley }
1447*412e9a14SMatthew G. Knepley 
1448*412e9a14SMatthew G. Knepley /* Construct cell type order since we must loop over cell types in depth order */
1449*412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCreateCellTypeOrder_Internal(DMPolytopeType ctCell, PetscInt *ctOrder[], PetscInt *ctOrderInv[])
1450*412e9a14SMatthew G. Knepley {
1451*412e9a14SMatthew G. Knepley   PetscInt      *ctO, *ctOInv;
1452*412e9a14SMatthew G. Knepley   PetscInt       c, d, off = 0;
1453*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1454*412e9a14SMatthew G. Knepley 
1455*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1456*412e9a14SMatthew G. Knepley   ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctO, DM_NUM_POLYTOPES+1, &ctOInv);CHKERRQ(ierr);
1457*412e9a14SMatthew G. Knepley   for (d = 3; d >= DMPolytopeTypeGetDim(ctCell); --d) {
1458*412e9a14SMatthew G. Knepley     for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
1459*412e9a14SMatthew G. Knepley       if (DMPolytopeTypeGetDim((DMPolytopeType) c) != d) continue;
1460*412e9a14SMatthew G. Knepley       ctO[off++] = c;
1461*412e9a14SMatthew G. Knepley     }
1462*412e9a14SMatthew G. Knepley   }
1463*412e9a14SMatthew G. Knepley   if (DMPolytopeTypeGetDim(ctCell) != 0) {
1464*412e9a14SMatthew G. Knepley     for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
1465*412e9a14SMatthew G. Knepley       if (DMPolytopeTypeGetDim((DMPolytopeType) c) != 0) continue;
1466*412e9a14SMatthew G. Knepley       ctO[off++] = c;
1467*412e9a14SMatthew G. Knepley     }
1468*412e9a14SMatthew G. Knepley   }
1469*412e9a14SMatthew G. Knepley   for (d = DMPolytopeTypeGetDim(ctCell)-1; d > 0; --d) {
1470*412e9a14SMatthew G. Knepley     for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
1471*412e9a14SMatthew G. Knepley       if (DMPolytopeTypeGetDim((DMPolytopeType) c) != d) continue;
1472*412e9a14SMatthew G. Knepley       ctO[off++] = c;
1473*412e9a14SMatthew G. Knepley     }
1474*412e9a14SMatthew G. Knepley   }
1475*412e9a14SMatthew G. Knepley   for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
1476*412e9a14SMatthew G. Knepley     if (DMPolytopeTypeGetDim((DMPolytopeType) c) >= 0) continue;
1477*412e9a14SMatthew G. Knepley     ctO[off++] = c;
1478*412e9a14SMatthew G. Knepley   }
1479*412e9a14SMatthew G. Knepley   if (off != DM_NUM_POLYTOPES+1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid offset %D for cell type order", off);
1480*412e9a14SMatthew G. Knepley   for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
1481*412e9a14SMatthew G. Knepley     ctOInv[ctO[c]] = c;
1482*412e9a14SMatthew G. Knepley   }
1483*412e9a14SMatthew G. Knepley   *ctOrder    = ctO;
1484*412e9a14SMatthew G. Knepley   *ctOrderInv = ctOInv;
1485*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1486*412e9a14SMatthew G. Knepley }
1487*412e9a14SMatthew G. Knepley 
1488*412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerSetUp(DMPlexCellRefiner cr)
1489*412e9a14SMatthew G. Knepley {
1490*412e9a14SMatthew G. Knepley   DM             dm = cr->dm;
1491*412e9a14SMatthew G. Knepley   DMPolytopeType ctCell;
1492*412e9a14SMatthew G. Knepley   PetscInt       pStart, pEnd, p, c;
1493*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1494*412e9a14SMatthew G. Knepley 
1495*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1496*412e9a14SMatthew G. Knepley   PetscValidHeader(cr, 1);
1497*412e9a14SMatthew G. Knepley   if (cr->setupcalled) PetscFunctionReturn(0);
1498*412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
1499*412e9a14SMatthew G. Knepley   if (pEnd > pStart) {ierr = DMPlexGetCellType(dm, 0, &ctCell);CHKERRQ(ierr);}
1500*412e9a14SMatthew G. Knepley   else               {
1501*412e9a14SMatthew G. Knepley     PetscInt dim;
1502a57030b0SMatthew G. Knepley     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1503*412e9a14SMatthew G. Knepley     switch (dim) {
1504*412e9a14SMatthew G. Knepley       case 0: ctCell = DM_POLYTOPE_POINT;break;
1505*412e9a14SMatthew G. Knepley       case 1: ctCell = DM_POLYTOPE_SEGMENT;break;
1506*412e9a14SMatthew G. Knepley       case 2: ctCell = DM_POLYTOPE_TRIANGLE;break;
1507*412e9a14SMatthew G. Knepley       case 3: ctCell = DM_POLYTOPE_TETRAHEDRON;break;
1508*412e9a14SMatthew G. Knepley       default: ctCell = DM_POLYTOPE_TETRAHEDRON;
1509*412e9a14SMatthew G. Knepley     }
1510*412e9a14SMatthew G. Knepley   }
1511*412e9a14SMatthew G. Knepley   ierr = DMPlexCreateCellTypeOrder_Internal(ctCell, &cr->ctOrder, &cr->ctOrderInv);CHKERRQ(ierr);
1512*412e9a14SMatthew G. Knepley   /* Construct sizes and offsets for each cell type */
1513*412e9a14SMatthew G. Knepley   if (!cr->ctStart) {
1514*412e9a14SMatthew G. Knepley     PetscInt *ctS, *ctSN, *ctC, *ctCN;
1515*412e9a14SMatthew G. Knepley 
1516*412e9a14SMatthew G. Knepley     ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctS, DM_NUM_POLYTOPES+1, &ctSN);CHKERRQ(ierr);
1517*412e9a14SMatthew G. Knepley     ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctC, DM_NUM_POLYTOPES+1, &ctCN);CHKERRQ(ierr);
1518*412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
1519*412e9a14SMatthew G. Knepley       DMPolytopeType  ct;
1520*412e9a14SMatthew G. Knepley       DMPolytopeType *rct;
1521*412e9a14SMatthew G. Knepley       PetscInt       *rsize, *cone, *ornt;
1522*412e9a14SMatthew G. Knepley       PetscInt        Nct, n;
1523*412e9a14SMatthew G. Knepley 
1524*412e9a14SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
1525*412e9a14SMatthew G. Knepley       if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell type for point %D", p);
1526*412e9a14SMatthew G. Knepley       ++ctC[ct];
1527*412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
1528*412e9a14SMatthew G. Knepley       for (n = 0; n < Nct; ++n) ctCN[rct[n]] += rsize[n];
1529*412e9a14SMatthew G. Knepley     }
1530*412e9a14SMatthew G. Knepley     for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1531*412e9a14SMatthew G. Knepley       const PetscInt ct  = cr->ctOrder[c];
1532*412e9a14SMatthew G. Knepley       const PetscInt ctn = cr->ctOrder[c+1];
1533*412e9a14SMatthew G. Knepley 
1534*412e9a14SMatthew G. Knepley       ctS[ctn]  = ctS[ct]  + ctC[ct];
1535*412e9a14SMatthew G. Knepley       ctSN[ctn] = ctSN[ct] + ctCN[ct];
1536*412e9a14SMatthew G. Knepley     }
1537*412e9a14SMatthew G. Knepley     ierr = PetscFree2(ctC, ctCN);CHKERRQ(ierr);
1538*412e9a14SMatthew G. Knepley     cr->ctStart    = ctS;
1539*412e9a14SMatthew G. Knepley     cr->ctStartNew = ctSN;
1540*412e9a14SMatthew G. Knepley   }
1541*412e9a14SMatthew G. Knepley   ierr = CellRefinerCreateOffset_Internal(cr, cr->ctOrder, cr->ctStart, &cr->offset);CHKERRQ(ierr);
1542*412e9a14SMatthew G. Knepley   cr->setupcalled = PETSC_TRUE;
1543*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1544*412e9a14SMatthew G. Knepley }
1545*412e9a14SMatthew G. Knepley 
1546*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerView_Ascii(DMPlexCellRefiner cr, PetscViewer v)
1547*412e9a14SMatthew G. Knepley {
1548*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1549*412e9a14SMatthew G. Knepley 
1550*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1551*412e9a14SMatthew G. Knepley   ierr = PetscViewerASCIIPrintf(v, "Cell Refiner: %s\n", DMPlexCellRefinerTypes[cr->type]);CHKERRQ(ierr);
1552*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1553*412e9a14SMatthew G. Knepley }
1554*412e9a14SMatthew G. Knepley 
1555*412e9a14SMatthew G. Knepley /*
1556*412e9a14SMatthew G. Knepley   DMPlexCellRefinerView - Views a DMPlexCellRefiner object
1557*412e9a14SMatthew G. Knepley 
1558*412e9a14SMatthew G. Knepley   Collective on cr
1559*412e9a14SMatthew G. Knepley 
1560*412e9a14SMatthew G. Knepley   Input Parameters:
1561*412e9a14SMatthew G. Knepley + cr     - The DMPlexCellRefiner object
1562*412e9a14SMatthew G. Knepley - viewer - The PetscViewer object
1563*412e9a14SMatthew G. Knepley 
1564*412e9a14SMatthew G. Knepley   Level: beginner
1565*412e9a14SMatthew G. Knepley 
1566*412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerCreate()
1567*412e9a14SMatthew G. Knepley */
1568*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerView(DMPlexCellRefiner cr, PetscViewer viewer)
1569*412e9a14SMatthew G. Knepley {
1570*412e9a14SMatthew G. Knepley   PetscBool      iascii;
1571*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1572*412e9a14SMatthew G. Knepley 
1573*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1574*412e9a14SMatthew G. Knepley   PetscValidHeader(cr, 1);
1575*412e9a14SMatthew G. Knepley   if (viewer) PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1576*412e9a14SMatthew G. Knepley   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) cr), &viewer);CHKERRQ(ierr);}
1577*412e9a14SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
1578*412e9a14SMatthew G. Knepley   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1579*412e9a14SMatthew G. Knepley   if (iascii) {ierr = DMPlexCellRefinerView_Ascii(cr, viewer);CHKERRQ(ierr);}
1580*412e9a14SMatthew G. Knepley   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1581*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1582*412e9a14SMatthew G. Knepley }
1583*412e9a14SMatthew G. Knepley 
1584*412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerDestroy(DMPlexCellRefiner *cr)
1585*412e9a14SMatthew G. Knepley {
1586*412e9a14SMatthew G. Knepley   PetscInt       c;
1587*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1588*412e9a14SMatthew G. Knepley 
1589*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1590*412e9a14SMatthew G. Knepley   if (!*cr) PetscFunctionReturn(0);
1591*412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(*cr, DM_CLASSID, 1);
1592*412e9a14SMatthew G. Knepley   ierr = PetscObjectDereference((PetscObject) (*cr)->dm);CHKERRQ(ierr);
1593*412e9a14SMatthew G. Knepley   ierr = PetscFree2((*cr)->ctOrder, (*cr)->ctOrderInv);CHKERRQ(ierr);
1594*412e9a14SMatthew G. Knepley   ierr = PetscFree2((*cr)->ctStart, (*cr)->ctStartNew);CHKERRQ(ierr);
1595*412e9a14SMatthew G. Knepley   ierr = PetscFree((*cr)->offset);CHKERRQ(ierr);
1596*412e9a14SMatthew G. Knepley   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1597*412e9a14SMatthew G. Knepley     ierr = PetscFEDestroy(&(*cr)->coordFE[c]);CHKERRQ(ierr);
1598*412e9a14SMatthew G. Knepley     ierr = PetscFEGeomDestroy(&(*cr)->refGeom[c]);CHKERRQ(ierr);
1599*412e9a14SMatthew G. Knepley   }
1600*412e9a14SMatthew G. Knepley   ierr = PetscFree2((*cr)->coordFE, (*cr)->refGeom);CHKERRQ(ierr);
1601*412e9a14SMatthew G. Knepley   ierr = PetscHeaderDestroy(cr);CHKERRQ(ierr);
1602*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1603*412e9a14SMatthew G. Knepley }
1604*412e9a14SMatthew G. Knepley 
1605*412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerCreate(DM dm, DMPlexCellRefiner *cr)
1606*412e9a14SMatthew G. Knepley {
1607*412e9a14SMatthew G. Knepley   DMPlexCellRefiner tmp;
1608*412e9a14SMatthew G. Knepley   PetscErrorCode    ierr;
1609*412e9a14SMatthew G. Knepley 
1610*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1611*412e9a14SMatthew G. Knepley   PetscValidPointer(cr, 2);
1612*412e9a14SMatthew G. Knepley   *cr  = NULL;
1613*412e9a14SMatthew G. Knepley   ierr = PetscHeaderCreate(tmp, DM_CLASSID, "DMPlexCellRefiner", "Cell Refiner", "DMPlexCellRefiner", PETSC_COMM_SELF, DMPlexCellRefinerDestroy, DMPlexCellRefinerView);CHKERRQ(ierr);
1614*412e9a14SMatthew G. Knepley   tmp->setupcalled = PETSC_FALSE;
1615*412e9a14SMatthew G. Knepley 
1616*412e9a14SMatthew G. Knepley   tmp->dm = dm;
1617*412e9a14SMatthew G. Knepley   ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
1618*412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellRefinerType(dm, &tmp->type);CHKERRQ(ierr);
1619*412e9a14SMatthew G. Knepley   switch (tmp->type) {
1620*412e9a14SMatthew G. Knepley     case REFINER_REGULAR:
1621*412e9a14SMatthew G. Knepley       tmp->ops->refine                  = DMPlexCellRefinerRefine_Regular;
1622*412e9a14SMatthew G. Knepley       tmp->ops->mapsubcells             = DMPlexCellRefinerMapSubcells_Regular;
1623*412e9a14SMatthew G. Knepley       tmp->ops->getcellvertices         = DMPlexCellRefinerGetCellVertices_Regular;
1624*412e9a14SMatthew G. Knepley       tmp->ops->getsubcellvertices      = DMPlexCellRefinerGetSubcellVertices_Regular;
1625*412e9a14SMatthew G. Knepley       tmp->ops->getaffinetransforms     = DMPlexCellRefinerGetAffineTransforms_Regular;
1626*412e9a14SMatthew G. Knepley       tmp->ops->getaffinefacetransforms = DMPlexCellRefinerGetAffineFaceTransforms_Regular;
1627*412e9a14SMatthew G. Knepley       break;
1628*412e9a14SMatthew G. Knepley     case REFINER_TO_HEX:
1629*412e9a14SMatthew G. Knepley       tmp->ops->refine             = DMPlexCellRefinerRefine_ToHex;
1630*412e9a14SMatthew G. Knepley       tmp->ops->mapsubcells        = DMPlexCellRefinerMapSubcells_ToHex;
1631*412e9a14SMatthew G. Knepley       tmp->ops->getcellvertices    = DMPlexCellRefinerGetCellVertices_ToHex;
1632*412e9a14SMatthew G. Knepley       tmp->ops->getsubcellvertices = DMPlexCellRefinerGetSubcellVertices_ToHex;
1633*412e9a14SMatthew G. Knepley       break;
1634*412e9a14SMatthew G. Knepley     case REFINER_TO_SIMPLEX:
1635*412e9a14SMatthew G. Knepley       tmp->ops->refine      = DMPlexCellRefinerRefine_ToSimplex;
1636*412e9a14SMatthew G. Knepley       tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_ToSimplex;
1637*412e9a14SMatthew G. Knepley       break;
1638*412e9a14SMatthew G. Knepley     default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Invalid cell refiner type %s", DMPlexCellRefinerTypes[tmp->type]);
1639*412e9a14SMatthew G. Knepley   }
1640*412e9a14SMatthew G. Knepley   ierr = PetscCalloc2(DM_NUM_POLYTOPES, &tmp->coordFE, DM_NUM_POLYTOPES, &tmp->refGeom);CHKERRQ(ierr);
1641*412e9a14SMatthew G. Knepley   *cr = tmp;
1642*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1643*412e9a14SMatthew G. Knepley }
1644*412e9a14SMatthew G. Knepley 
1645*412e9a14SMatthew G. Knepley /*@
1646*412e9a14SMatthew G. Knepley   DMPlexCellRefinerGetAffineTransforms - Gets the affine map from the reference cell to each subcell
1647*412e9a14SMatthew G. Knepley 
1648*412e9a14SMatthew G. Knepley   Input Parameters:
1649*412e9a14SMatthew G. Knepley + cr - The DMPlexCellRefiner object
1650*412e9a14SMatthew G. Knepley - ct - The cell type
1651*412e9a14SMatthew G. Knepley 
1652*412e9a14SMatthew G. Knepley   Output Parameters:
1653*412e9a14SMatthew G. Knepley + Nc   - The number of subcells produced from this cell type
1654*412e9a14SMatthew G. Knepley . v0   - The translation of the first vertex for each subcell
1655*412e9a14SMatthew G. Knepley . J    - The Jacobian for each subcell (map from reference cell to subcell)
1656*412e9a14SMatthew G. Knepley - invJ - The inverse Jacobian for each subcell
1657*412e9a14SMatthew G. Knepley 
1658*412e9a14SMatthew G. Knepley   Level: developer
1659*412e9a14SMatthew G. Knepley 
1660*412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerGetAffineFaceTransforms(), Create()
1661*412e9a14SMatthew G. Knepley @*/
1662*412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerGetAffineTransforms(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nc, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[])
1663*412e9a14SMatthew G. Knepley {
1664*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1665*412e9a14SMatthew G. Knepley 
1666*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1667*412e9a14SMatthew G. Knepley   if (!cr->ops->getaffinetransforms) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_SUP, "No support for affine transforms from this refiner");
1668*412e9a14SMatthew G. Knepley   ierr = (*cr->ops->getaffinetransforms)(cr, ct, Nc, v0, J, invJ);CHKERRQ(ierr);
1669*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1670*412e9a14SMatthew G. Knepley }
1671*412e9a14SMatthew G. Knepley 
1672*412e9a14SMatthew G. Knepley /*@
1673*412e9a14SMatthew G. Knepley   DMPlexCellRefinerGetAffineFaceTransforms - Gets the affine map from the reference face cell to each face in the given cell
1674*412e9a14SMatthew G. Knepley 
1675*412e9a14SMatthew G. Knepley   Input Parameters:
1676*412e9a14SMatthew G. Knepley + cr - The DMPlexCellRefiner object
1677*412e9a14SMatthew G. Knepley - ct - The cell type
1678*412e9a14SMatthew G. Knepley 
1679*412e9a14SMatthew G. Knepley   Output Parameters:
1680*412e9a14SMatthew G. Knepley + Nf   - The number of faces for this cell type
1681*412e9a14SMatthew G. Knepley . v0   - The translation of the first vertex for each face
1682*412e9a14SMatthew G. Knepley . J    - The Jacobian for each face (map from original cell to subcell)
1683*412e9a14SMatthew G. Knepley . invJ - The inverse Jacobian for each face
1684*412e9a14SMatthew G. Knepley - detJ - The determinant of the Jacobian for each face
1685*412e9a14SMatthew G. Knepley 
1686*412e9a14SMatthew G. Knepley   Note: The Jacobian and inverse Jacboian will be rectangular, and the inverse is really a generalized inverse.
1687*412e9a14SMatthew G. Knepley 
1688*412e9a14SMatthew G. Knepley   Level: developer
1689*412e9a14SMatthew G. Knepley 
1690*412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerGetAffineTransforms(), Create()
1691*412e9a14SMatthew G. Knepley @*/
1692*412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerGetAffineFaceTransforms(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nf, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[], PetscReal *detJ[])
1693*412e9a14SMatthew G. Knepley {
1694*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1695*412e9a14SMatthew G. Knepley 
1696*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1697*412e9a14SMatthew G. Knepley   if (!cr->ops->getaffinefacetransforms) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_SUP, "No support for affine face transforms from this refiner");
1698*412e9a14SMatthew G. Knepley   ierr = (*cr->ops->getaffinefacetransforms)(cr, ct, Nf, v0, J, invJ, detJ);CHKERRQ(ierr);
1699*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1700*412e9a14SMatthew G. Knepley }
1701*412e9a14SMatthew G. Knepley 
1702*412e9a14SMatthew G. Knepley /* Numbering regularly refined meshes
1703*412e9a14SMatthew G. Knepley 
1704*412e9a14SMatthew G. Knepley    We want the numbering of the new mesh to respect the same depth stratification as the old mesh. We first compute
1705*412e9a14SMatthew G. Knepley    the number of new points at each depth. This means that offsets for each depth can be computed, making no assumptions
1706*412e9a14SMatthew G. Knepley    about the order of different cell types.
1707*412e9a14SMatthew G. Knepley 
1708*412e9a14SMatthew G. Knepley    However, when we want to order different depth strata, it will be very useful to make assumptions about contiguous
1709*412e9a14SMatthew G. Knepley    numbering of different cell types, especially if we want to compute new numberings without communication. Therefore, we
1710*412e9a14SMatthew G. Knepley    will require that cells are numbering contiguously for each cell type, and that those blocks come in the same order as
1711*412e9a14SMatthew G. Knepley    the cell type enumeration within a given depth stratum.
1712*412e9a14SMatthew G. Knepley 
1713*412e9a14SMatthew G. Knepley    Thus, at each depth, each cell type will add a certain number of points at that depth. To get the new point number, we
1714*412e9a14SMatthew G. Knepley    start at the new depth offset, run through all prior cell types incrementing by the total addition from that type, then
1715*412e9a14SMatthew G. Knepley    offset by the old cell type number and replica number for the insertion.
1716*412e9a14SMatthew G. Knepley */
1717*412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerGetNewPoint(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType ctNew, PetscInt p, PetscInt r, PetscInt *pNew)
1718*412e9a14SMatthew G. Knepley {
1719*412e9a14SMatthew G. Knepley   DMPolytopeType  *rct;
1720*412e9a14SMatthew G. Knepley   PetscInt        *rsize, *cone, *ornt;
1721*412e9a14SMatthew G. Knepley   PetscInt         Nct, n;
1722*412e9a14SMatthew G. Knepley   PetscInt         off  = cr->offset[ct*DM_NUM_POLYTOPES+ctNew];
1723*412e9a14SMatthew G. Knepley   PetscInt         ctS  = cr->ctStart[ct],       ctE  = cr->ctStart[cr->ctOrder[cr->ctOrderInv[ct]+1]];
1724*412e9a14SMatthew G. Knepley   PetscInt         ctSN = cr->ctStartNew[ctNew], ctEN = cr->ctStartNew[cr->ctOrder[cr->ctOrderInv[ctNew]+1]];
1725*412e9a14SMatthew G. Knepley   PetscInt         newp = ctSN;
1726*412e9a14SMatthew G. Knepley   PetscErrorCode   ierr;
1727*412e9a14SMatthew G. Knepley 
1728*412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
1729*412e9a14SMatthew G. Knepley   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);
1730*412e9a14SMatthew G. Knepley   if (off < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s does not produce type %s", DMPolytopeTypes[ct], DMPolytopeTypes[ctNew]);
1731*412e9a14SMatthew G. Knepley 
1732*412e9a14SMatthew G. Knepley   newp += off;
1733*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
1734*412e9a14SMatthew G. Knepley   for (n = 0; n < Nct; ++n) {
1735*412e9a14SMatthew G. Knepley     if (rct[n] == ctNew) {
1736*412e9a14SMatthew G. Knepley       if (rsize[n] && r >= rsize[n])
1737*412e9a14SMatthew G. Knepley         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]);
1738*412e9a14SMatthew G. Knepley       newp += (p - ctS) * rsize[n] + r;
1739*412e9a14SMatthew G. Knepley       break;
1740*412e9a14SMatthew G. Knepley     }
1741*412e9a14SMatthew G. Knepley   }
1742*412e9a14SMatthew G. Knepley 
1743*412e9a14SMatthew G. Knepley   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);
1744*412e9a14SMatthew G. Knepley   *pNew = newp;
1745*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1746*412e9a14SMatthew G. Knepley }
1747*412e9a14SMatthew G. Knepley 
1748*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerSetConeSizes(DMPlexCellRefiner cr, DM rdm)
1749*412e9a14SMatthew G. Knepley {
1750*412e9a14SMatthew G. Knepley   DM              dm = cr->dm;
1751*412e9a14SMatthew G. Knepley   PetscInt        pStart, pEnd, p, pNew;
1752*412e9a14SMatthew G. Knepley   PetscErrorCode  ierr;
1753*412e9a14SMatthew G. Knepley 
1754*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1755*412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
1756*412e9a14SMatthew G. Knepley   ierr = DMCreateLabel(rdm, "celltype");CHKERRQ(ierr);
1757*412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
1758*412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
1759*412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
1760*412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
1761*412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
1762*412e9a14SMatthew G. Knepley     PetscInt        Nct, n, r;
1763*412e9a14SMatthew G. Knepley 
1764*412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
1765*412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
1766*412e9a14SMatthew G. Knepley     for (n = 0; n < Nct; ++n) {
1767*412e9a14SMatthew G. Knepley       for (r = 0; r < rsize[n]; ++r) {
1768*412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
1769*412e9a14SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, pNew, DMPolytopeTypeGetConeSize(rct[n]));CHKERRQ(ierr);
1770*412e9a14SMatthew G. Knepley         ierr = DMPlexSetCellType(rdm, pNew, rct[n]);CHKERRQ(ierr);
1771*412e9a14SMatthew G. Knepley       }
1772*412e9a14SMatthew G. Knepley     }
1773*412e9a14SMatthew G. Knepley   }
1774*412e9a14SMatthew G. Knepley   {
1775*412e9a14SMatthew G. Knepley     DMLabel  ctLabel;
1776*412e9a14SMatthew G. Knepley     DM_Plex *plex = (DM_Plex *) rdm->data;
1777*412e9a14SMatthew G. Knepley 
1778*412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellTypeLabel(rdm, &ctLabel);CHKERRQ(ierr);
1779*412e9a14SMatthew G. Knepley     ierr = PetscObjectStateGet((PetscObject) ctLabel, &plex->celltypeState);CHKERRQ(ierr);
1780*412e9a14SMatthew G. Knepley   }
1781*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1782*412e9a14SMatthew G. Knepley }
1783*412e9a14SMatthew G. Knepley 
1784*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerSetCones(DMPlexCellRefiner cr, DM rdm)
1785*412e9a14SMatthew G. Knepley {
1786*412e9a14SMatthew G. Knepley   DM             dm = cr->dm;
1787*412e9a14SMatthew G. Knepley   DMPolytopeType ct;
1788*412e9a14SMatthew G. Knepley   PetscInt      *coneNew, *orntNew;
1789*412e9a14SMatthew G. Knepley   PetscInt       maxConeSize = 0, pStart, pEnd, p, pNew;
1790*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1791*412e9a14SMatthew G. Knepley 
1792*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1793*412e9a14SMatthew G. Knepley   for (p = 0; p < DM_NUM_POLYTOPES; ++p) maxConeSize = PetscMax(maxConeSize, DMPolytopeTypeGetConeSize((DMPolytopeType) p));
1794*412e9a14SMatthew G. Knepley   ierr = PetscMalloc2(maxConeSize, &coneNew, maxConeSize, &orntNew);CHKERRQ(ierr);
1795*412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
1796*412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
1797*412e9a14SMatthew G. Knepley     const PetscInt *cone, *ornt;
1798*412e9a14SMatthew G. Knepley     PetscInt        coff, ooff, c;
1799*412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
1800*412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
1801*412e9a14SMatthew G. Knepley     PetscInt        Nct, n, r;
1802*412e9a14SMatthew G. Knepley 
1803*412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
1804*412e9a14SMatthew G. Knepley     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
1805*412e9a14SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr);
1806*412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
1807*412e9a14SMatthew G. Knepley     for (n = 0, coff = 0, ooff = 0; n < Nct; ++n) {
1808*412e9a14SMatthew G. Knepley       const DMPolytopeType ctNew    = rct[n];
1809*412e9a14SMatthew G. Knepley       const PetscInt       csizeNew = DMPolytopeTypeGetConeSize(ctNew);
1810*412e9a14SMatthew G. Knepley 
1811*412e9a14SMatthew G. Knepley       for (r = 0; r < rsize[n]; ++r) {
1812*412e9a14SMatthew G. Knepley         /* pNew is a subcell produced by subdividing p */
1813*412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
1814*412e9a14SMatthew G. Knepley         for (c = 0; c < csizeNew; ++c) {
1815*412e9a14SMatthew G. Knepley           PetscInt             ppp   = -1;                             /* Parent Parent point: Parent of point pp */
1816*412e9a14SMatthew G. Knepley           PetscInt             pp    = p;                              /* Parent point: Point in the original mesh producing new cone point */
1817*412e9a14SMatthew G. Knepley           PetscInt             po    = 0;                              /* Orientation of parent point pp in parent parent point ppp */
1818*412e9a14SMatthew G. Knepley           DMPolytopeType       pct   = ct;                             /* Parent type:  Cell type for parent of new cone point */
1819*412e9a14SMatthew G. Knepley           const PetscInt      *pcone = cone;                           /* Parent cone: Cone of parent point pp */
1820*412e9a14SMatthew G. Knepley           PetscInt             pr    = -1;                             /* Replica number of pp that produces new cone point  */
1821*412e9a14SMatthew G. Knepley           const DMPolytopeType ft    = (DMPolytopeType) rcone[coff++]; /* Cell type for new cone point of pNew */
1822*412e9a14SMatthew G. Knepley           const PetscInt       fn    = rcone[coff++];                  /* Number of cones of p that need to be taken when producing new cone point */
1823*412e9a14SMatthew G. Knepley           PetscInt             fo    = rornt[ooff++];                  /* Orientation of new cone point in pNew */
1824*412e9a14SMatthew G. Knepley           PetscInt             lc;
1825*412e9a14SMatthew G. Knepley 
1826*412e9a14SMatthew G. Knepley           /* Get the type (pct) and point number (pp) of the parent point in the original mesh which produces this cone point */
1827*412e9a14SMatthew G. Knepley           for (lc = 0; lc < fn; ++lc) {
1828*412e9a14SMatthew G. Knepley             const PetscInt *ppornt;
1829*412e9a14SMatthew G. Knepley             PetscInt        pcp;
1830*412e9a14SMatthew G. Knepley 
1831*412e9a14SMatthew G. Knepley             ierr = DMPolytopeMapCell(pct, po, rcone[coff++], &pcp);CHKERRQ(ierr);
1832*412e9a14SMatthew G. Knepley             ppp  = pp;
1833*412e9a14SMatthew G. Knepley             pp   = pcone[pcp];
1834*412e9a14SMatthew G. Knepley             ierr = DMPlexGetCellType(dm, pp, &pct);CHKERRQ(ierr);
1835*412e9a14SMatthew G. Knepley             ierr = DMPlexGetCone(dm, pp, &pcone);CHKERRQ(ierr);
1836*412e9a14SMatthew G. Knepley             ierr = DMPlexGetConeOrientation(dm, ppp, &ppornt);CHKERRQ(ierr);
1837*412e9a14SMatthew G. Knepley             po   = ppornt[pcp];
1838*412e9a14SMatthew G. Knepley           }
1839*412e9a14SMatthew G. Knepley           pr = rcone[coff++];
1840*412e9a14SMatthew G. Knepley           /* Orientation po of pp maps (pr, fo) -> (pr', fo') */
1841*412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerMapSubcells(cr, pct, po, ft, pr, fo, &pr, &fo);CHKERRQ(ierr);
1842*412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(cr, pct, ft, pp, pr, &coneNew[c]);CHKERRQ(ierr);
1843*412e9a14SMatthew G. Knepley           orntNew[c] = fo;
1844*412e9a14SMatthew G. Knepley         }
1845*412e9a14SMatthew G. Knepley         ierr = DMPlexSetCone(rdm, pNew, coneNew);CHKERRQ(ierr);
1846*412e9a14SMatthew G. Knepley         ierr = DMPlexSetConeOrientation(rdm, pNew, orntNew);CHKERRQ(ierr);
1847*412e9a14SMatthew G. Knepley       }
1848*412e9a14SMatthew G. Knepley     }
1849*412e9a14SMatthew G. Knepley   }
1850*412e9a14SMatthew G. Knepley   ierr = PetscFree2(coneNew, orntNew);CHKERRQ(ierr);
1851*412e9a14SMatthew G. Knepley   ierr = DMPlexSymmetrize(rdm);CHKERRQ(ierr);
1852*412e9a14SMatthew G. Knepley   ierr = DMPlexStratify(rdm);CHKERRQ(ierr);
1853*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1854*412e9a14SMatthew G. Knepley }
1855*412e9a14SMatthew G. Knepley 
1856*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetCoordinateFE(DMPlexCellRefiner cr, DMPolytopeType ct, PetscFE *fe)
1857*412e9a14SMatthew G. Knepley {
1858*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1859*412e9a14SMatthew G. Knepley 
1860*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1861*412e9a14SMatthew G. Knepley   if (!cr->coordFE[ct]) {
1862*412e9a14SMatthew G. Knepley     PetscInt  dim, cdim;
1863*412e9a14SMatthew G. Knepley     PetscBool isSimplex;
1864*412e9a14SMatthew G. Knepley 
1865*412e9a14SMatthew G. Knepley     switch (ct) {
1866*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:       dim = 1; isSimplex = PETSC_TRUE;  break;
1867*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:      dim = 2; isSimplex = PETSC_TRUE;  break;
1868*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL: dim = 2; isSimplex = PETSC_FALSE; break;
1869*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:   dim = 3; isSimplex = PETSC_TRUE;  break;
1870*412e9a14SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:    dim = 3; isSimplex = PETSC_FALSE; break;
1871*412e9a14SMatthew G. Knepley       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No coordinate FE for cell type %s", DMPolytopeTypes[ct]);
1872*412e9a14SMatthew G. Knepley     }
1873*412e9a14SMatthew G. Knepley     ierr = DMGetCoordinateDim(cr->dm, &cdim);CHKERRQ(ierr);
1874*412e9a14SMatthew G. Knepley     ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, cdim, isSimplex, 1, PETSC_DETERMINE, &cr->coordFE[ct]);CHKERRQ(ierr);
1875*412e9a14SMatthew G. Knepley     {
1876*412e9a14SMatthew G. Knepley       PetscDualSpace  dsp;
1877*412e9a14SMatthew G. Knepley       PetscQuadrature quad;
1878*412e9a14SMatthew G. Knepley       DM              K;
1879*412e9a14SMatthew G. Knepley       PetscFEGeom    *cg;
1880*412e9a14SMatthew G. Knepley       PetscReal      *Xq, *xq, *wq;
1881*412e9a14SMatthew G. Knepley       PetscInt        Nq, q;
1882*412e9a14SMatthew G. Knepley 
1883*412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerGetCellVertices(cr, ct, &Nq, &Xq);CHKERRQ(ierr);
1884*412e9a14SMatthew G. Knepley       ierr = PetscMalloc1(Nq*cdim, &xq);CHKERRQ(ierr);
1885*412e9a14SMatthew G. Knepley       for (q = 0; q < Nq*cdim; ++q) xq[q] = Xq[q];
1886*412e9a14SMatthew G. Knepley       ierr = PetscMalloc1(Nq, &wq);CHKERRQ(ierr);
1887*412e9a14SMatthew G. Knepley       for (q = 0; q < Nq; ++q) wq[q] = 1.0;
1888*412e9a14SMatthew G. Knepley       ierr = PetscQuadratureCreate(PETSC_COMM_SELF, &quad);CHKERRQ(ierr);
1889*412e9a14SMatthew G. Knepley       ierr = PetscQuadratureSetData(quad, dim, 1, Nq, xq, wq);CHKERRQ(ierr);
1890*412e9a14SMatthew G. Knepley       ierr = PetscFESetQuadrature(cr->coordFE[ct], quad);CHKERRQ(ierr);
1891*412e9a14SMatthew G. Knepley 
1892*412e9a14SMatthew G. Knepley       ierr = PetscFEGetDualSpace(cr->coordFE[ct], &dsp);CHKERRQ(ierr);
1893*412e9a14SMatthew G. Knepley       ierr = PetscDualSpaceGetDM(dsp, &K);CHKERRQ(ierr);
1894*412e9a14SMatthew G. Knepley       ierr = PetscFEGeomCreate(quad, 1, cdim, PETSC_FALSE, &cr->refGeom[ct]);CHKERRQ(ierr);
1895*412e9a14SMatthew G. Knepley       cg   = cr->refGeom[ct];
1896*412e9a14SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(K, 0, NULL, cg->v, cg->J, cg->invJ, cg->detJ);CHKERRQ(ierr);
1897*412e9a14SMatthew G. Knepley       ierr = PetscQuadratureDestroy(&quad);CHKERRQ(ierr);
1898*412e9a14SMatthew G. Knepley     }
1899*412e9a14SMatthew G. Knepley   }
1900*412e9a14SMatthew G. Knepley   *fe = cr->coordFE[ct];
1901*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1902*412e9a14SMatthew G. Knepley }
1903*412e9a14SMatthew G. Knepley 
1904*412e9a14SMatthew G. Knepley /*
1905*412e9a14SMatthew G. Knepley   DMPlexCellRefinerMapLocalizedCoordinates - Given a cell of type ct with localized coordinates x, we generate localized coordinates xr for subcell r of type rct.
1906*412e9a14SMatthew G. Knepley 
1907*412e9a14SMatthew G. Knepley   Not collective
1908*412e9a14SMatthew G. Knepley 
1909*412e9a14SMatthew G. Knepley   Input Parameters:
1910*412e9a14SMatthew G. Knepley + cr  - The DMPlexCellRefiner
1911*412e9a14SMatthew G. Knepley . ct  - The type of the parent cell
1912*412e9a14SMatthew G. Knepley . rct - The type of the produced cell
1913*412e9a14SMatthew G. Knepley . r   - The index of the produced cell
1914*412e9a14SMatthew G. Knepley - x   - The localized coordinates for the parent cell
1915*412e9a14SMatthew G. Knepley 
1916*412e9a14SMatthew G. Knepley   Output Parameter:
1917*412e9a14SMatthew G. Knepley . xr  - The localized coordinates for the produced cell
1918*412e9a14SMatthew G. Knepley 
1919*412e9a14SMatthew G. Knepley   Level: developer
1920*412e9a14SMatthew G. Knepley 
1921*412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerSetCoordinates()
1922*412e9a14SMatthew G. Knepley */
1923*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapLocalizedCoordinates(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, const PetscScalar x[], PetscScalar xr[])
1924*412e9a14SMatthew G. Knepley {
1925*412e9a14SMatthew G. Knepley   PetscFE        fe = NULL;
1926*412e9a14SMatthew G. Knepley   PetscInt       cdim, Nv, v, *subcellV;
1927*412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1928*412e9a14SMatthew G. Knepley 
1929*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1930*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerGetCoordinateFE(cr, ct, &fe);CHKERRQ(ierr);
1931*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerGetSubcellVertices(cr, ct, rct, r, &Nv, &subcellV);CHKERRQ(ierr);
1932*412e9a14SMatthew G. Knepley   ierr = PetscFEGetNumComponents(fe, &cdim);CHKERRQ(ierr);
1933*412e9a14SMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
1934*412e9a14SMatthew G. Knepley     ierr = PetscFEInterpolate_Static(fe, x, cr->refGeom[ct], subcellV[v], &xr[v*cdim]);CHKERRQ(ierr);
1935*412e9a14SMatthew G. Knepley   }
1936*412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1937*412e9a14SMatthew G. Knepley }
1938*412e9a14SMatthew G. Knepley 
1939*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerSetCoordinates(DMPlexCellRefiner cr, DM rdm)
1940*412e9a14SMatthew G. Knepley {
1941*412e9a14SMatthew G. Knepley   DM                    dm = cr->dm, cdm;
1942*412e9a14SMatthew G. Knepley   PetscSection          coordSection, coordSectionNew;
1943*412e9a14SMatthew G. Knepley   Vec                   coordsLocal, coordsLocalNew;
1944*412e9a14SMatthew G. Knepley   const PetscScalar    *coords;
1945*412e9a14SMatthew G. Knepley   PetscScalar          *coordsNew;
1946*412e9a14SMatthew G. Knepley   const DMBoundaryType *bd;
1947*412e9a14SMatthew G. Knepley   const PetscReal      *maxCell, *L;
1948*412e9a14SMatthew G. Knepley   PetscBool             isperiodic, localizeVertices = PETSC_FALSE, localizeCells = PETSC_FALSE;
1949*412e9a14SMatthew G. Knepley   PetscInt              dE, d, cStart, cEnd, c, vStartNew, vEndNew, v, pStart, pEnd, p, ocStart, ocEnd;
1950*412e9a14SMatthew G. Knepley   PetscErrorCode        ierr;
1951*412e9a14SMatthew G. Knepley 
1952*412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1953*412e9a14SMatthew G. Knepley   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
195490b157c4SStefano Zampini   ierr = DMGetPeriodicity(dm, &isperiodic, &maxCell, &L, &bd);CHKERRQ(ierr);
195590b157c4SStefano Zampini   /* Determine if we need to localize coordinates when generating them */
1956b9ccc978SStefano Zampini   if (isperiodic) {
1957*412e9a14SMatthew G. Knepley     localizeVertices = PETSC_TRUE;
1958*412e9a14SMatthew G. Knepley     if (!maxCell) {
1959*412e9a14SMatthew G. Knepley       PetscBool localized;
1960*412e9a14SMatthew G. Knepley       ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
1961*412e9a14SMatthew G. Knepley       if (!localized) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Cannot refine a periodic mesh if coordinates have not been localized");
1962*412e9a14SMatthew G. Knepley       localizeCells = PETSC_TRUE;
1963b9ccc978SStefano Zampini     }
1964b9ccc978SStefano Zampini   }
1965b9ccc978SStefano Zampini 
1966b9ccc978SStefano Zampini   ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
1967*412e9a14SMatthew G. Knepley   ierr = PetscSectionGetFieldComponents(coordSection, 0, &dE);CHKERRQ(ierr);
1968*412e9a14SMatthew G. Knepley   if (maxCell) {
1969*412e9a14SMatthew G. Knepley     PetscReal maxCellNew[3];
1970*412e9a14SMatthew G. Knepley 
1971*412e9a14SMatthew G. Knepley     for (d = 0; d < dE; ++d) maxCellNew[d] = maxCell[d]/2.0;
1972*412e9a14SMatthew G. Knepley     ierr = DMSetPeriodicity(rdm, isperiodic, maxCellNew, L, bd);CHKERRQ(ierr);
1973*412e9a14SMatthew G. Knepley   } else {
1974*412e9a14SMatthew G. Knepley     ierr = DMSetPeriodicity(rdm, isperiodic, maxCell, L, bd);CHKERRQ(ierr);
1975*412e9a14SMatthew G. Knepley   }
1976b9ccc978SStefano Zampini   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &coordSectionNew);CHKERRQ(ierr);
1977b9ccc978SStefano Zampini   ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr);
1978*412e9a14SMatthew G. Knepley   ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dE);CHKERRQ(ierr);
1979*412e9a14SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(rdm, 0, &vStartNew, &vEndNew);CHKERRQ(ierr);
1980*412e9a14SMatthew G. Knepley   if (localizeCells) {ierr = PetscSectionSetChart(coordSectionNew, 0,         vEndNew);CHKERRQ(ierr);}
1981*412e9a14SMatthew G. Knepley   else               {ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vEndNew);CHKERRQ(ierr);}
1982b9ccc978SStefano Zampini 
1983*412e9a14SMatthew G. Knepley   /* Localization should be inherited */
1984*412e9a14SMatthew G. Knepley   /*   Stefano calculates parent cells for each new cell for localization */
1985*412e9a14SMatthew G. Knepley   /*   Localized cells need coordinates of closure */
1986*412e9a14SMatthew G. Knepley   for (v = vStartNew; v < vEndNew; ++v) {
1987*412e9a14SMatthew G. Knepley     ierr = PetscSectionSetDof(coordSectionNew, v, dE);CHKERRQ(ierr);
1988*412e9a14SMatthew G. Knepley     ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dE);CHKERRQ(ierr);
1989*412e9a14SMatthew G. Knepley   }
1990*412e9a14SMatthew G. Knepley   if (localizeCells) {
1991*412e9a14SMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1992*412e9a14SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1993*412e9a14SMatthew G. Knepley       PetscInt dof;
199490b157c4SStefano Zampini 
1995*412e9a14SMatthew G. Knepley       ierr = PetscSectionGetDof(coordSection, c, &dof); CHKERRQ(ierr);
1996*412e9a14SMatthew G. Knepley       if (dof) {
1997*412e9a14SMatthew G. Knepley         DMPolytopeType  ct;
1998*412e9a14SMatthew G. Knepley         DMPolytopeType *rct;
1999*412e9a14SMatthew G. Knepley         PetscInt       *rsize, *rcone, *rornt;
2000*412e9a14SMatthew G. Knepley         PetscInt        dim, cNew, Nct, n, r;
200190b157c4SStefano Zampini 
2002*412e9a14SMatthew G. Knepley         ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
2003*412e9a14SMatthew G. Knepley         dim  = DMPolytopeTypeGetDim(ct);
2004*412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
2005*412e9a14SMatthew G. Knepley         /* This allows for different cell types */
2006*412e9a14SMatthew G. Knepley         for (n = 0; n < Nct; ++n) {
2007*412e9a14SMatthew G. Knepley           if (dim != DMPolytopeTypeGetDim(rct[n])) continue;
2008*412e9a14SMatthew G. Knepley           for (r = 0; r < rsize[n]; ++r) {
2009*412e9a14SMatthew G. Knepley             PetscInt *closure = NULL;
2010*412e9a14SMatthew G. Knepley             PetscInt  clSize, cl, Nv = 0;
201190b157c4SStefano Zampini 
2012*412e9a14SMatthew G. Knepley             ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], c, r, &cNew);CHKERRQ(ierr);
2013*412e9a14SMatthew G. Knepley             ierr = DMPlexGetTransitiveClosure(rdm, cNew, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
2014*412e9a14SMatthew G. Knepley             for (cl = 0; cl < clSize*2; cl += 2) {if ((closure[cl] >= vStartNew) && (closure[cl] < vEndNew)) ++Nv;}
2015*412e9a14SMatthew G. Knepley             ierr = DMPlexRestoreTransitiveClosure(rdm, cNew, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
2016*412e9a14SMatthew G. Knepley             ierr = PetscSectionSetDof(coordSectionNew, cNew, Nv * dE);CHKERRQ(ierr);
2017*412e9a14SMatthew G. Knepley             ierr = PetscSectionSetFieldDof(coordSectionNew, cNew, 0, Nv * dE);CHKERRQ(ierr);
20189fc2a3f3SStefano Zampini           }
201990b157c4SStefano Zampini         }
202090b157c4SStefano Zampini       }
2021*412e9a14SMatthew G. Knepley     }
202275d3a19aSMatthew G. Knepley   }
202375d3a19aSMatthew G. Knepley   ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr);
2024*412e9a14SMatthew G. Knepley   ierr = DMViewFromOptions(dm, NULL, "-coarse_dm_view");CHKERRQ(ierr);
202546e270d4SMatthew G. Knepley   ierr = DMSetCoordinateSection(rdm, PETSC_DETERMINE, coordSectionNew);CHKERRQ(ierr);
2026*412e9a14SMatthew G. Knepley   {
2027*412e9a14SMatthew G. Knepley     VecType     vtype;
2028*412e9a14SMatthew G. Knepley     PetscInt    coordSizeNew, bs;
2029*412e9a14SMatthew G. Knepley     const char *name;
2030*412e9a14SMatthew G. Knepley 
2031*412e9a14SMatthew G. Knepley     ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
2032*412e9a14SMatthew G. Knepley     ierr = VecCreate(PETSC_COMM_SELF, &coordsLocalNew);CHKERRQ(ierr);
203375d3a19aSMatthew G. Knepley     ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr);
2034*412e9a14SMatthew G. Knepley     ierr = VecSetSizes(coordsLocalNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr);
2035*412e9a14SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) coordsLocal, &name);CHKERRQ(ierr);
2036*412e9a14SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) coordsLocalNew, name);CHKERRQ(ierr);
2037*412e9a14SMatthew G. Knepley     ierr = VecGetBlockSize(coordsLocal, &bs);CHKERRQ(ierr);
2038*412e9a14SMatthew G. Knepley     ierr = VecSetBlockSize(coordsLocalNew, bs);CHKERRQ(ierr);
2039*412e9a14SMatthew G. Knepley     ierr = VecGetType(coordsLocal, &vtype);CHKERRQ(ierr);
2040*412e9a14SMatthew G. Knepley     ierr = VecSetType(coordsLocalNew, vtype);CHKERRQ(ierr);
2041b5da9499SMatthew G. Knepley   }
2042*412e9a14SMatthew G. Knepley   ierr = VecGetArrayRead(coordsLocal, &coords);CHKERRQ(ierr);
2043*412e9a14SMatthew G. Knepley   ierr = VecGetArray(coordsLocalNew, &coordsNew);CHKERRQ(ierr);
2044*412e9a14SMatthew G. Knepley   ierr = PetscSectionGetChart(coordSection, &ocStart, &ocEnd);CHKERRQ(ierr);
2045*412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
2046*412e9a14SMatthew G. Knepley   /* First set coordinates for vertices*/
2047*412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
2048*412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
2049*412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
2050*412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
2051*412e9a14SMatthew G. Knepley     PetscInt        Nct, n, r;
2052*412e9a14SMatthew G. Knepley     PetscBool       hasVertex = PETSC_FALSE, isLocalized = PETSC_FALSE;
205390b157c4SStefano Zampini 
2054*412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
2055*412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
2056*412e9a14SMatthew G. Knepley     for (n = 0; n < Nct; ++n) {
2057*412e9a14SMatthew G. Knepley       if (rct[n] == DM_POLYTOPE_POINT) {hasVertex = PETSC_TRUE; break;}
2058*412e9a14SMatthew G. Knepley     }
2059*412e9a14SMatthew G. Knepley     if (localizeVertices && ct != DM_POLYTOPE_POINT && (p >= ocStart) && (p < ocEnd)) {
2060*412e9a14SMatthew G. Knepley       PetscInt dof;
2061*412e9a14SMatthew G. Knepley       ierr = PetscSectionGetDof(coordSection, p, &dof); CHKERRQ(ierr);
2062*412e9a14SMatthew G. Knepley       if (dof) isLocalized = PETSC_TRUE;
2063*412e9a14SMatthew G. Knepley     }
2064*412e9a14SMatthew G. Knepley     if (hasVertex) {
2065*412e9a14SMatthew G. Knepley       PetscScalar *pcoords = NULL;
2066*412e9a14SMatthew G. Knepley       PetscScalar  vcoords[3] = {0., 0., 0.};
2067*412e9a14SMatthew G. Knepley       PetscInt     Nc, Nv, v, d;
206890b157c4SStefano Zampini 
2069*412e9a14SMatthew G. Knepley       ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, p, &Nc, &pcoords);CHKERRQ(ierr);
2070*412e9a14SMatthew G. Knepley       if (ct == DM_POLYTOPE_POINT) {
2071*412e9a14SMatthew G. Knepley         for (d = 0; d < dE; ++d) vcoords[d] = pcoords[d];
20729fc2a3f3SStefano Zampini       } else {
2073*412e9a14SMatthew G. Knepley         if (localizeVertices) {
2074*412e9a14SMatthew G. Knepley           PetscScalar anchor[3];
207590b157c4SStefano Zampini 
2076*412e9a14SMatthew G. Knepley           for (d = 0; d < dE; ++d) anchor[d] = pcoords[d];
2077*412e9a14SMatthew G. Knepley           if (!isLocalized) {
2078*412e9a14SMatthew G. Knepley             Nv = Nc/dE;
2079*412e9a14SMatthew G. Knepley             for (v = 0; v < Nv; ++v) {ierr = DMLocalizeAddCoordinate_Internal(dm, dE, anchor, &pcoords[v*dE], vcoords);CHKERRQ(ierr);}
2080*412e9a14SMatthew G. Knepley           } else {
2081*412e9a14SMatthew G. Knepley             Nv = Nc/(2*dE);
2082*412e9a14SMatthew G. Knepley             for (v = Nv; v < Nv*2; ++v) {ierr = DMLocalizeAddCoordinate_Internal(dm, dE, anchor, &pcoords[v*dE], vcoords);CHKERRQ(ierr);}
208390b157c4SStefano Zampini           }
208490b157c4SStefano Zampini         } else {
2085*412e9a14SMatthew G. Knepley           Nv = Nc/dE;
2086*412e9a14SMatthew G. Knepley           for (v = 0; v < Nv; ++v) for (d = 0; d < dE; ++d) vcoords[d] += pcoords[v*dE+d];
2087b5da9499SMatthew G. Knepley         }
2088*412e9a14SMatthew G. Knepley         for (d = 0; d < dE; ++d) vcoords[d] /= Nv;
208990b157c4SStefano Zampini       }
2090*412e9a14SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, p, &Nc, &pcoords);CHKERRQ(ierr);
2091*412e9a14SMatthew G. Knepley       for (n = 0; n < Nct; ++n) {
2092*412e9a14SMatthew G. Knepley         if (rct[n] != DM_POLYTOPE_POINT) continue;
2093*412e9a14SMatthew G. Knepley         for (r = 0; r < rsize[n]; ++r) {
2094*412e9a14SMatthew G. Knepley           PetscInt vNew, off;
2095b5da9499SMatthew G. Knepley 
2096*412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &vNew);CHKERRQ(ierr);
2097*412e9a14SMatthew G. Knepley           ierr = PetscSectionGetOffset(coordSectionNew, vNew, &off);CHKERRQ(ierr);
2098*412e9a14SMatthew G. Knepley           for (d = 0; d < dE; ++d) coordsNew[off+d] = vcoords[d];
2099b5da9499SMatthew G. Knepley         }
21009fc2a3f3SStefano Zampini       }
2101*412e9a14SMatthew G. Knepley     }
2102*412e9a14SMatthew G. Knepley   }
2103*412e9a14SMatthew G. Knepley   /* Then set coordinates for cells by localizing */
2104*412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
2105*412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
2106*412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
2107*412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
2108*412e9a14SMatthew G. Knepley     PetscInt        Nct, n, r;
2109*412e9a14SMatthew G. Knepley     PetscBool       isLocalized = PETSC_FALSE;
211090b157c4SStefano Zampini 
2111*412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
2112*412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
2113*412e9a14SMatthew G. Knepley     if (localizeCells && ct != DM_POLYTOPE_POINT && (p >= ocStart) && (p < ocEnd)) {
2114*412e9a14SMatthew G. Knepley       PetscInt dof;
2115*412e9a14SMatthew G. Knepley       ierr = PetscSectionGetDof(coordSection, p, &dof); CHKERRQ(ierr);
2116*412e9a14SMatthew G. Knepley       if (dof) isLocalized = PETSC_TRUE;
2117b5da9499SMatthew G. Knepley     }
2118*412e9a14SMatthew G. Knepley     if (isLocalized) {
2119*412e9a14SMatthew G. Knepley       const PetscScalar *pcoords;
21209fc2a3f3SStefano Zampini 
2121*412e9a14SMatthew G. Knepley       ierr = DMPlexPointLocalRead(cdm, p, coords, &pcoords);CHKERRQ(ierr);
2122*412e9a14SMatthew G. Knepley       for (n = 0; n < Nct; ++n) {
2123*412e9a14SMatthew G. Knepley         const PetscInt Nr = rsize[n];
212490b157c4SStefano Zampini 
2125*412e9a14SMatthew G. Knepley         if (DMPolytopeTypeGetDim(ct) != DMPolytopeTypeGetDim(rct[n])) continue;
2126*412e9a14SMatthew G. Knepley         for (r = 0; r < Nr; ++r) {
2127*412e9a14SMatthew G. Knepley           PetscInt pNew, offNew;
212890b157c4SStefano Zampini 
2129*412e9a14SMatthew G. Knepley           /* It looks like Stefano and Lisandro are allowing localized coordinates without defining the periodic boundary, which means that
2130*412e9a14SMatthew G. Knepley              DMLocalizeCoordinate_Internal() will not work. Localized coordinates will have to have obtained by the affine map of the larger
2131*412e9a14SMatthew G. Knepley              cell to the ones it produces. */
2132*412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
2133*412e9a14SMatthew G. Knepley           ierr = PetscSectionGetOffset(coordSectionNew, pNew, &offNew);CHKERRQ(ierr);
2134*412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerMapLocalizedCoordinates(cr, ct, rct[n], r, pcoords, &coordsNew[offNew]);CHKERRQ(ierr);
213590b157c4SStefano Zampini         }
213690b157c4SStefano Zampini       }
213790b157c4SStefano Zampini     }
213890b157c4SStefano Zampini   }
2139*412e9a14SMatthew G. Knepley   ierr = VecRestoreArrayRead(coordsLocal, &coords);CHKERRQ(ierr);
2140*412e9a14SMatthew G. Knepley   ierr = VecRestoreArray(coordsLocalNew, &coordsNew);CHKERRQ(ierr);
2141*412e9a14SMatthew G. Knepley   ierr = DMSetCoordinatesLocal(rdm, coordsLocalNew);CHKERRQ(ierr);
2142*412e9a14SMatthew G. Knepley   /* TODO Stefano has a final reduction if some hybrid coordinates cannot be found. (needcoords) Should not be needed. */
2143*412e9a14SMatthew G. Knepley   ierr = VecDestroy(&coordsLocalNew);CHKERRQ(ierr);
214475d3a19aSMatthew G. Knepley   ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr);
2145*412e9a14SMatthew G. Knepley   if (!localizeCells) {ierr = DMLocalizeCoordinates(rdm);CHKERRQ(ierr);}
214675d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
214775d3a19aSMatthew G. Knepley }
214875d3a19aSMatthew G. Knepley 
2149963fc26aSMatthew G. Knepley /*@
2150963fc26aSMatthew G. Knepley   DMPlexCreateProcessSF - Create an SF which just has process connectivity
2151963fc26aSMatthew G. Knepley 
2152d083f849SBarry Smith   Collective on dm
2153963fc26aSMatthew G. Knepley 
2154963fc26aSMatthew G. Knepley   Input Parameters:
2155963fc26aSMatthew G. Knepley + dm      - The DM
2156963fc26aSMatthew G. Knepley - sfPoint - The PetscSF which encodes point connectivity
2157963fc26aSMatthew G. Knepley 
2158963fc26aSMatthew G. Knepley   Output Parameters:
2159963fc26aSMatthew G. Knepley + processRanks - A list of process neighbors, or NULL
2160963fc26aSMatthew G. Knepley - sfProcess    - An SF encoding the process connectivity, or NULL
2161963fc26aSMatthew G. Knepley 
2162963fc26aSMatthew G. Knepley   Level: developer
2163963fc26aSMatthew G. Knepley 
2164963fc26aSMatthew G. Knepley .seealso: PetscSFCreate(), DMPlexCreateTwoSidedProcessSF()
2165963fc26aSMatthew G. Knepley @*/
2166963fc26aSMatthew G. Knepley PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
216775d3a19aSMatthew G. Knepley {
216875d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, l;
216975d3a19aSMatthew G. Knepley   const PetscInt    *localPoints;
217075d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
217175d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
217275d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
217375d3a19aSMatthew G. Knepley   PetscInt          *ranks, *ranksNew;
21749852e123SBarry Smith   PetscMPIInt        size;
217575d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
217675d3a19aSMatthew G. Knepley 
217775d3a19aSMatthew G. Knepley   PetscFunctionBegin;
2178963fc26aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2179963fc26aSMatthew G. Knepley   PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2);
2180963fc26aSMatthew G. Knepley   if (processRanks) {PetscValidPointer(processRanks, 3);}
2181963fc26aSMatthew G. Knepley   if (sfProcess)    {PetscValidPointer(sfProcess, 4);}
21829852e123SBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRQ(ierr);
218375d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
2184785e854fSJed Brown   ierr = PetscMalloc1(numLeaves, &ranks);CHKERRQ(ierr);
218575d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
218675d3a19aSMatthew G. Knepley     ranks[l] = remotePoints[l].rank;
218775d3a19aSMatthew G. Knepley   }
218875d3a19aSMatthew G. Knepley   ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr);
2189785e854fSJed Brown   ierr = PetscMalloc1(numLeaves, &ranksNew);CHKERRQ(ierr);
2190785e854fSJed Brown   ierr = PetscMalloc1(numLeaves, &localPointsNew);CHKERRQ(ierr);
2191785e854fSJed Brown   ierr = PetscMalloc1(numLeaves, &remotePointsNew);CHKERRQ(ierr);
219275d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
219375d3a19aSMatthew G. Knepley     ranksNew[l]              = ranks[l];
219475d3a19aSMatthew G. Knepley     localPointsNew[l]        = l;
219575d3a19aSMatthew G. Knepley     remotePointsNew[l].index = 0;
219675d3a19aSMatthew G. Knepley     remotePointsNew[l].rank  = ranksNew[l];
219775d3a19aSMatthew G. Knepley   }
219875d3a19aSMatthew G. Knepley   ierr = PetscFree(ranks);CHKERRQ(ierr);
2199963fc26aSMatthew G. Knepley   if (processRanks) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);}
2200963fc26aSMatthew G. Knepley   else              {ierr = PetscFree(ranksNew);CHKERRQ(ierr);}
2201963fc26aSMatthew G. Knepley   if (sfProcess) {
220275d3a19aSMatthew G. Knepley     ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr);
2203963fc26aSMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) *sfProcess, "Process SF");CHKERRQ(ierr);
220475d3a19aSMatthew G. Knepley     ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr);
22059852e123SBarry Smith     ierr = PetscSFSetGraph(*sfProcess, size, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
2206963fc26aSMatthew G. Knepley   }
220775d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
220875d3a19aSMatthew G. Knepley }
220975d3a19aSMatthew G. Knepley 
2210*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerCreateSF(DMPlexCellRefiner cr, DM rdm)
221175d3a19aSMatthew G. Knepley {
2212*412e9a14SMatthew G. Knepley   DM                 dm = cr->dm;
2213*412e9a14SMatthew G. Knepley   DMPlexCellRefiner *crRem;
221475d3a19aSMatthew G. Knepley   PetscSF            sf, sfNew, sfProcess;
221575d3a19aSMatthew G. Knepley   IS                 processRanks;
2216*412e9a14SMatthew G. Knepley   MPI_Datatype       ctType;
221775d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
221875d3a19aSMatthew G. Knepley   const PetscInt    *localPoints, *neighbors;
221975d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
222075d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
222175d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
2222*412e9a14SMatthew G. Knepley   PetscInt          *ctStartRem, *ctStartNewRem;
2223*412e9a14SMatthew G. Knepley   PetscInt           ctSize = DM_NUM_POLYTOPES+1, numNeighbors, n, pStartNew, pEndNew, pNew, pNewRem;
222475d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
222575d3a19aSMatthew G. Knepley 
222675d3a19aSMatthew G. Knepley   PetscFunctionBegin;
222775d3a19aSMatthew G. Knepley   ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr);
222875d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
222975d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr);
2230add09238SMatthew G. Knepley   /* Calculate size of new SF */
223175d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
223275d3a19aSMatthew G. Knepley   if (numRoots < 0) PetscFunctionReturn(0);
223375d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
223475d3a19aSMatthew G. Knepley     const PetscInt  p = localPoints[l];
2235*412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
2236*412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
2237*412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
2238*412e9a14SMatthew G. Knepley     PetscInt        Nct, n;
223975d3a19aSMatthew G. Knepley 
2240*412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
2241*412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
2242*412e9a14SMatthew G. Knepley     for (n = 0; n < Nct; ++n) numLeavesNew += rsize[n];
22430314a74cSLawrence Mitchell   }
2244*412e9a14SMatthew G. Knepley   /* Communicate ctStart and cStartNew for each remote rank */
224575d3a19aSMatthew G. Knepley   ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr);
224675d3a19aSMatthew G. Knepley   ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr);
2247*412e9a14SMatthew G. Knepley   ierr = PetscMalloc2(ctSize*numNeighbors, &ctStartRem, ctSize*numNeighbors, &ctStartNewRem);CHKERRQ(ierr);
2248*412e9a14SMatthew G. Knepley   ierr = MPI_Type_contiguous(ctSize, MPIU_INT, &ctType);CHKERRQ(ierr);
2249*412e9a14SMatthew G. Knepley   ierr = MPI_Type_commit(&ctType);CHKERRQ(ierr);
2250*412e9a14SMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, ctType, cr->ctStart, ctStartRem);CHKERRQ(ierr);
2251*412e9a14SMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, ctType, cr->ctStart, ctStartRem);CHKERRQ(ierr);
2252*412e9a14SMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, ctType, cr->ctStartNew, ctStartNewRem);CHKERRQ(ierr);
2253*412e9a14SMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, ctType, cr->ctStartNew, ctStartNewRem);CHKERRQ(ierr);
2254*412e9a14SMatthew G. Knepley   ierr = MPI_Type_free(&ctType);CHKERRQ(ierr);
225575d3a19aSMatthew G. Knepley   ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr);
2256*412e9a14SMatthew G. Knepley   ierr = PetscMalloc1(numNeighbors, &crRem);CHKERRQ(ierr);
2257*412e9a14SMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {
2258*412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerCreate(dm, &crRem[n]);CHKERRQ(ierr);
2259*412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerSetStarts(crRem[n], &ctStartRem[n*ctSize], &ctStartNewRem[n*ctSize]);
2260*412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerSetUp(crRem[n]);CHKERRQ(ierr);
2261*412e9a14SMatthew G. Knepley   }
2262*412e9a14SMatthew G. Knepley   ierr = PetscFree2(ctStartRem, ctStartNewRem);CHKERRQ(ierr);
226375d3a19aSMatthew G. Knepley   /* Calculate new point SF */
2264785e854fSJed Brown   ierr = PetscMalloc1(numLeavesNew, &localPointsNew);CHKERRQ(ierr);
2265785e854fSJed Brown   ierr = PetscMalloc1(numLeavesNew, &remotePointsNew);CHKERRQ(ierr);
226675d3a19aSMatthew G. Knepley   ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr);
226775d3a19aSMatthew G. Knepley   for (l = 0, m = 0; l < numLeaves; ++l) {
226875d3a19aSMatthew G. Knepley     PetscInt        p       = localPoints[l];
2269*412e9a14SMatthew G. Knepley     PetscInt        pRem    = remotePoints[l].index;
2270*412e9a14SMatthew G. Knepley     PetscMPIInt     rankRem = remotePoints[l].rank;
2271*412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
2272*412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
2273*412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
2274*412e9a14SMatthew G. Knepley     PetscInt        neighbor, Nct, n, r;
227575d3a19aSMatthew G. Knepley 
2276*412e9a14SMatthew G. Knepley     ierr = PetscFindInt(rankRem, numNeighbors, neighbors, &neighbor);CHKERRQ(ierr);
2277*412e9a14SMatthew G. Knepley     if (neighbor < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %D", rankRem);
2278*412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
2279*412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
2280*412e9a14SMatthew G. Knepley     for (n = 0; n < Nct; ++n) {
2281*412e9a14SMatthew G. Knepley       for (r = 0; r < rsize[n]; ++r) {
2282*412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
2283*412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerGetNewPoint(crRem[neighbor], ct, rct[n], pRem, r, &pNewRem);CHKERRQ(ierr);
2284*412e9a14SMatthew G. Knepley         localPointsNew[m]        = pNew;
2285*412e9a14SMatthew G. Knepley         remotePointsNew[m].index = pNewRem;
2286*412e9a14SMatthew G. Knepley         remotePointsNew[m].rank  = rankRem;
22870314a74cSLawrence Mitchell         ++m;
22880314a74cSLawrence Mitchell       }
22896ce3c06aSMatthew G. Knepley     }
22906ce3c06aSMatthew G. Knepley   }
2291*412e9a14SMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {ierr = DMPlexCellRefinerDestroy(&crRem[n]);CHKERRQ(ierr);}
2292*412e9a14SMatthew G. Knepley   ierr = PetscFree(crRem);CHKERRQ(ierr);
2293d7eabd03SStefano Zampini   if (m != numLeavesNew) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of leaf point %D should be %D", m, numLeavesNew);
229475d3a19aSMatthew G. Knepley   ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr);
229575d3a19aSMatthew G. Knepley   ierr = ISDestroy(&processRanks);CHKERRQ(ierr);
2296ba3c3d50SMatthew G. Knepley   {
2297ba3c3d50SMatthew G. Knepley     PetscSFNode *rp, *rtmp;
2298ba3c3d50SMatthew G. Knepley     PetscInt    *lp, *idx, *ltmp, i;
2299ba3c3d50SMatthew G. Knepley 
2300ba3c3d50SMatthew G. Knepley     /* SF needs sorted leaves to correct calculate Gather */
2301ba3c3d50SMatthew G. Knepley     ierr = PetscMalloc1(numLeavesNew, &idx);CHKERRQ(ierr);
2302ba3c3d50SMatthew G. Knepley     ierr = PetscMalloc1(numLeavesNew, &lp);CHKERRQ(ierr);
2303ba3c3d50SMatthew G. Knepley     ierr = PetscMalloc1(numLeavesNew, &rp);CHKERRQ(ierr);
2304c7c54c77SMatthew G. Knepley     for (i = 0; i < numLeavesNew; ++i) {
2305d7eabd03SStefano Zampini       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);
2306c7c54c77SMatthew G. Knepley       idx[i] = i;
2307c7c54c77SMatthew G. Knepley     }
2308ba3c3d50SMatthew G. Knepley     ierr = PetscSortIntWithPermutation(numLeavesNew, localPointsNew, idx);CHKERRQ(ierr);
2309ba3c3d50SMatthew G. Knepley     for (i = 0; i < numLeavesNew; ++i) {
2310ba3c3d50SMatthew G. Knepley       lp[i] = localPointsNew[idx[i]];
2311ba3c3d50SMatthew G. Knepley       rp[i] = remotePointsNew[idx[i]];
2312ba3c3d50SMatthew G. Knepley     }
2313ba3c3d50SMatthew G. Knepley     ltmp            = localPointsNew;
2314ba3c3d50SMatthew G. Knepley     localPointsNew  = lp;
2315ba3c3d50SMatthew G. Knepley     rtmp            = remotePointsNew;
2316ba3c3d50SMatthew G. Knepley     remotePointsNew = rp;
2317ba3c3d50SMatthew G. Knepley     ierr = PetscFree(idx);CHKERRQ(ierr);
2318ba3c3d50SMatthew G. Knepley     ierr = PetscFree(ltmp);CHKERRQ(ierr);
2319ba3c3d50SMatthew G. Knepley     ierr = PetscFree(rtmp);CHKERRQ(ierr);
2320ba3c3d50SMatthew G. Knepley   }
232175d3a19aSMatthew G. Knepley   ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
232275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
232375d3a19aSMatthew G. Knepley }
232475d3a19aSMatthew G. Knepley 
2325*412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerCreateLabels(DMPlexCellRefiner cr, DM rdm)
232675d3a19aSMatthew G. Knepley {
2327*412e9a14SMatthew G. Knepley   DM             dm = cr->dm;
232875d3a19aSMatthew G. Knepley   PetscInt       numLabels, l;
2329*412e9a14SMatthew G. Knepley   PetscInt       pNew;
233075d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
233175d3a19aSMatthew G. Knepley 
233275d3a19aSMatthew G. Knepley   PetscFunctionBegin;
2333c58f1c22SToby Isaac   ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
233475d3a19aSMatthew G. Knepley   for (l = 0; l < numLabels; ++l) {
233575d3a19aSMatthew G. Knepley     DMLabel         label, labelNew;
233675d3a19aSMatthew G. Knepley     const char     *lname;
2337ba2698f1SMatthew G. Knepley     PetscBool       isDepth, isCellType;
233875d3a19aSMatthew G. Knepley     IS              valueIS;
233975d3a19aSMatthew G. Knepley     const PetscInt *values;
23405aa44df4SToby Isaac     PetscInt        defVal;
234175d3a19aSMatthew G. Knepley     PetscInt        numValues, val;
234275d3a19aSMatthew G. Knepley 
2343c58f1c22SToby Isaac     ierr = DMGetLabelName(dm, l, &lname);CHKERRQ(ierr);
234475d3a19aSMatthew G. Knepley     ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr);
234575d3a19aSMatthew G. Knepley     if (isDepth) continue;
2346ba2698f1SMatthew G. Knepley     ierr = PetscStrcmp(lname, "celltype", &isCellType);CHKERRQ(ierr);
2347ba2698f1SMatthew G. Knepley     if (isCellType) continue;
2348c58f1c22SToby Isaac     ierr = DMCreateLabel(rdm, lname);CHKERRQ(ierr);
2349c58f1c22SToby Isaac     ierr = DMGetLabel(dm, lname, &label);CHKERRQ(ierr);
2350c58f1c22SToby Isaac     ierr = DMGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr);
23515aa44df4SToby Isaac     ierr = DMLabelGetDefaultValue(label, &defVal);CHKERRQ(ierr);
23525aa44df4SToby Isaac     ierr = DMLabelSetDefaultValue(labelNew, defVal);CHKERRQ(ierr);
235375d3a19aSMatthew G. Knepley     ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
235475d3a19aSMatthew G. Knepley     ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr);
235575d3a19aSMatthew G. Knepley     ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
235675d3a19aSMatthew G. Knepley     for (val = 0; val < numValues; ++val) {
235775d3a19aSMatthew G. Knepley       IS              pointIS;
235875d3a19aSMatthew G. Knepley       const PetscInt *points;
2359*412e9a14SMatthew G. Knepley       PetscInt        numPoints, p;
236075d3a19aSMatthew G. Knepley 
23612bc5314cSMichael Lange       /* Ensure refined label is created with same number of strata as
23622bc5314cSMichael Lange        * original (even if no entries here). */
2363ad8374ffSToby Isaac       ierr = DMLabelAddStratum(labelNew, values[val]);CHKERRQ(ierr);
2364*412e9a14SMatthew G. Knepley       ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr);
2365*412e9a14SMatthew G. Knepley       ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
2366*412e9a14SMatthew G. Knepley       ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
2367*412e9a14SMatthew G. Knepley       for (p = 0; p < numPoints; ++p) {
2368*412e9a14SMatthew G. Knepley         const PetscInt  point = points[p];
2369*412e9a14SMatthew G. Knepley         DMPolytopeType  ct;
2370*412e9a14SMatthew G. Knepley         DMPolytopeType *rct;
2371*412e9a14SMatthew G. Knepley         PetscInt       *rsize, *rcone, *rornt;
2372*412e9a14SMatthew G. Knepley         PetscInt        Nct, n, r;
2373*412e9a14SMatthew G. Knepley 
2374*412e9a14SMatthew G. Knepley         ierr = DMPlexGetCellType(dm, point, &ct);CHKERRQ(ierr);
2375*412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
2376*412e9a14SMatthew G. Knepley         for (n = 0; n < Nct; ++n) {
2377*412e9a14SMatthew G. Knepley           for (r = 0; r < rsize[n]; ++r) {
2378*412e9a14SMatthew G. Knepley             ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], point, r, &pNew);CHKERRQ(ierr);
2379*412e9a14SMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, pNew, values[val]);CHKERRQ(ierr);
238027fcede3SMatthew G. Knepley           }
238175d3a19aSMatthew G. Knepley         }
238275d3a19aSMatthew G. Knepley       }
238375d3a19aSMatthew G. Knepley       ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
238475d3a19aSMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
238575d3a19aSMatthew G. Knepley     }
238675d3a19aSMatthew G. Knepley     ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
238775d3a19aSMatthew G. Knepley     ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
238875d3a19aSMatthew G. Knepley   }
238975d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
239075d3a19aSMatthew G. Knepley }
239175d3a19aSMatthew G. Knepley 
239275d3a19aSMatthew G. Knepley /* This will only work for interpolated meshes */
2393*412e9a14SMatthew G. Knepley PetscErrorCode DMPlexRefineUniform(DM dm, DMPlexCellRefiner cr, DM *dmRefined)
239475d3a19aSMatthew G. Knepley {
239575d3a19aSMatthew G. Knepley   DM              rdm;
2396*412e9a14SMatthew G. Knepley   PetscInt        dim, embedDim, depth;
239775d3a19aSMatthew G. Knepley   PetscErrorCode  ierr;
239875d3a19aSMatthew G. Knepley 
239975d3a19aSMatthew G. Knepley   PetscFunctionBegin;
2400*412e9a14SMatthew G. Knepley   PetscValidHeader(cr, 1);
240175d3a19aSMatthew G. Knepley   ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr);
240275d3a19aSMatthew G. Knepley   ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr);
2403c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
2404c73cfb54SMatthew G. Knepley   ierr = DMSetDimension(rdm, dim);CHKERRQ(ierr);
24056dcbd917SStefano Zampini   ierr = DMGetCoordinateDim(dm, &embedDim);CHKERRQ(ierr);
24066dcbd917SStefano Zampini   ierr = DMSetCoordinateDim(rdm, embedDim);CHKERRQ(ierr);
240775d3a19aSMatthew G. Knepley   /* Calculate number of new points of each depth */
240875d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
24091e573d11SMatthew G. Knepley   if (depth >= 0 && dim != depth) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated for regular refinement");
241075d3a19aSMatthew G. Knepley   /* Step 1: Set chart */
2411*412e9a14SMatthew G. Knepley   ierr = DMPlexSetChart(rdm, 0, cr->ctStartNew[cr->ctOrder[DM_NUM_POLYTOPES]]);CHKERRQ(ierr);
24126d7373e8SToby Isaac   /* Step 2: Set cone/support sizes (automatically stratifies) */
2413*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerSetConeSizes(cr, rdm);CHKERRQ(ierr);
241475d3a19aSMatthew G. Knepley   /* Step 3: Setup refined DM */
241575d3a19aSMatthew G. Knepley   ierr = DMSetUp(rdm);CHKERRQ(ierr);
24166d7373e8SToby Isaac   /* Step 4: Set cones and supports (automatically symmetrizes) */
2417*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerSetCones(cr, rdm);CHKERRQ(ierr);
24186d7373e8SToby Isaac   /* Step 5: Create pointSF */
2419*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerCreateSF(cr, rdm);CHKERRQ(ierr);
24206d7373e8SToby Isaac   /* Step 6: Create labels */
2421*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerCreateLabels(cr, rdm);CHKERRQ(ierr);
24226d7373e8SToby Isaac   /* Step 7: Set coordinates */
2423*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerSetCoordinates(cr, rdm);CHKERRQ(ierr);
242475d3a19aSMatthew G. Knepley   *dmRefined = rdm;
242575d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
242675d3a19aSMatthew G. Knepley }
242775d3a19aSMatthew G. Knepley 
24282389894bSMatthew G. Knepley /*@
24292389894bSMatthew G. Knepley   DMPlexCreateCoarsePointIS - Creates an IS covering the coarse DM chart with the fine points as data
24302389894bSMatthew G. Knepley 
24312389894bSMatthew G. Knepley   Input Parameter:
24322389894bSMatthew G. Knepley . dm - The coarse DM
24332389894bSMatthew G. Knepley 
24342389894bSMatthew G. Knepley   Output Parameter:
24352389894bSMatthew G. Knepley . fpointIS - The IS of all the fine points which exist in the original coarse mesh
24362389894bSMatthew G. Knepley 
24372389894bSMatthew G. Knepley   Level: developer
24382389894bSMatthew G. Knepley 
24392389894bSMatthew G. Knepley .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexCreateSubpointIS()
24402389894bSMatthew G. Knepley @*/
24412389894bSMatthew G. Knepley PetscErrorCode DMPlexCreateCoarsePointIS(DM dm, IS *fpointIS)
24422389894bSMatthew G. Knepley {
2443*412e9a14SMatthew G. Knepley   DMPlexCellRefiner cr;
2444*412e9a14SMatthew G. Knepley   PetscInt         *fpoints;
2445*412e9a14SMatthew G. Knepley   PetscInt          pStart, pEnd, p, vStart, vEnd, v, vNew;
24462389894bSMatthew G. Knepley   PetscErrorCode    ierr;
24472389894bSMatthew G. Knepley 
24482389894bSMatthew G. Knepley   PetscFunctionBegin;
24492389894bSMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
24502389894bSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
2451*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerCreate(dm, &cr);CHKERRQ(ierr);
2452*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
24532389894bSMatthew G. Knepley   ierr = PetscMalloc1(pEnd-pStart, &fpoints);CHKERRQ(ierr);
24542389894bSMatthew G. Knepley   for (p = 0; p < pEnd-pStart; ++p) fpoints[p] = -1;
2455*412e9a14SMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
2456*412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerGetNewPoint(cr, DM_POLYTOPE_POINT, DM_POLYTOPE_POINT, p, 0, &vNew);CHKERRQ(ierr);
2457*412e9a14SMatthew G. Knepley     fpoints[v-pStart] = vNew;
24582389894bSMatthew G. Knepley   }
2459*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
24602389894bSMatthew G. Knepley   ierr = ISCreateGeneral(PETSC_COMM_SELF, pEnd-pStart, fpoints, PETSC_OWN_POINTER, fpointIS);CHKERRQ(ierr);
24612389894bSMatthew G. Knepley   PetscFunctionReturn(0);
24622389894bSMatthew G. Knepley }
24632389894bSMatthew G. Knepley 
24640e2b6761SMatthew G. Knepley /*@
24650e2b6761SMatthew G. Knepley   DMPlexSetRefinementUniform - Set the flag for uniform refinement
24660e2b6761SMatthew G. Knepley 
24670e2b6761SMatthew G. Knepley   Input Parameters:
24680e2b6761SMatthew G. Knepley + dm - The DM
24690e2b6761SMatthew G. Knepley - refinementUniform - The flag for uniform refinement
24700e2b6761SMatthew G. Knepley 
24710e2b6761SMatthew G. Knepley   Level: developer
24720e2b6761SMatthew G. Knepley 
24730e2b6761SMatthew G. Knepley .seealso: DMRefine(), DMPlexGetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
24740e2b6761SMatthew G. Knepley @*/
247575d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
247675d3a19aSMatthew G. Knepley {
247775d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
247875d3a19aSMatthew G. Knepley 
247975d3a19aSMatthew G. Knepley   PetscFunctionBegin;
248075d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
248175d3a19aSMatthew G. Knepley   mesh->refinementUniform = refinementUniform;
248275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
248375d3a19aSMatthew G. Knepley }
248475d3a19aSMatthew G. Knepley 
24850e2b6761SMatthew G. Knepley /*@
24860e2b6761SMatthew G. Knepley   DMPlexGetRefinementUniform - Retrieve the flag for uniform refinement
24870e2b6761SMatthew G. Knepley 
24880e2b6761SMatthew G. Knepley   Input Parameter:
24890e2b6761SMatthew G. Knepley . dm - The DM
24900e2b6761SMatthew G. Knepley 
24910e2b6761SMatthew G. Knepley   Output Parameter:
24920e2b6761SMatthew G. Knepley . refinementUniform - The flag for uniform refinement
24930e2b6761SMatthew G. Knepley 
24940e2b6761SMatthew G. Knepley   Level: developer
24950e2b6761SMatthew G. Knepley 
24960e2b6761SMatthew G. Knepley .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
24970e2b6761SMatthew G. Knepley @*/
249875d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
249975d3a19aSMatthew G. Knepley {
250075d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
250175d3a19aSMatthew G. Knepley 
250275d3a19aSMatthew G. Knepley   PetscFunctionBegin;
250375d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
250475d3a19aSMatthew G. Knepley   PetscValidPointer(refinementUniform,  2);
250575d3a19aSMatthew G. Knepley   *refinementUniform = mesh->refinementUniform;
250675d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
250775d3a19aSMatthew G. Knepley }
250875d3a19aSMatthew G. Knepley 
25090e2b6761SMatthew G. Knepley /*@
25100e2b6761SMatthew G. Knepley   DMPlexSetRefinementLimit - Set the maximum cell volume for refinement
25110e2b6761SMatthew G. Knepley 
25120e2b6761SMatthew G. Knepley   Input Parameters:
25130e2b6761SMatthew G. Knepley + dm - The DM
25140e2b6761SMatthew G. Knepley - refinementLimit - The maximum cell volume in the refined mesh
25150e2b6761SMatthew G. Knepley 
25160e2b6761SMatthew G. Knepley   Level: developer
25170e2b6761SMatthew G. Knepley 
25180e2b6761SMatthew G. Knepley .seealso: DMRefine(), DMPlexGetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
25190e2b6761SMatthew G. Knepley @*/
252075d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
252175d3a19aSMatthew G. Knepley {
252275d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
252375d3a19aSMatthew G. Knepley 
252475d3a19aSMatthew G. Knepley   PetscFunctionBegin;
252575d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
252675d3a19aSMatthew G. Knepley   mesh->refinementLimit = refinementLimit;
252775d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
252875d3a19aSMatthew G. Knepley }
252975d3a19aSMatthew G. Knepley 
25300e2b6761SMatthew G. Knepley /*@
25310e2b6761SMatthew G. Knepley   DMPlexGetRefinementLimit - Retrieve the maximum cell volume for refinement
25320e2b6761SMatthew G. Knepley 
25330e2b6761SMatthew G. Knepley   Input Parameter:
25340e2b6761SMatthew G. Knepley . dm - The DM
25350e2b6761SMatthew G. Knepley 
25360e2b6761SMatthew G. Knepley   Output Parameter:
25370e2b6761SMatthew G. Knepley . refinementLimit - The maximum cell volume in the refined mesh
25380e2b6761SMatthew G. Knepley 
25390e2b6761SMatthew G. Knepley   Level: developer
25400e2b6761SMatthew G. Knepley 
25410e2b6761SMatthew G. Knepley .seealso: DMRefine(), DMPlexSetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
25420e2b6761SMatthew G. Knepley @*/
254375d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
254475d3a19aSMatthew G. Knepley {
254575d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
254675d3a19aSMatthew G. Knepley 
254775d3a19aSMatthew G. Knepley   PetscFunctionBegin;
254875d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
254975d3a19aSMatthew G. Knepley   PetscValidPointer(refinementLimit,  2);
255075d3a19aSMatthew G. Knepley   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
255175d3a19aSMatthew G. Knepley   *refinementLimit = mesh->refinementLimit;
255275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
255375d3a19aSMatthew G. Knepley }
255475d3a19aSMatthew G. Knepley 
2555b28003e6SMatthew G. Knepley /*@
2556b28003e6SMatthew G. Knepley   DMPlexSetRefinementFunction - Set the function giving the maximum cell volume for refinement
2557b28003e6SMatthew G. Knepley 
2558b28003e6SMatthew G. Knepley   Input Parameters:
2559b28003e6SMatthew G. Knepley + dm - The DM
2560b28003e6SMatthew G. Knepley - refinementFunc - Function giving the maximum cell volume in the refined mesh
2561b28003e6SMatthew G. Knepley 
2562b28003e6SMatthew G. Knepley   Note: The calling sequence is refinementFunc(coords, limit)
2563b28003e6SMatthew G. Knepley $ coords - Coordinates of the current point, usually a cell centroid
2564b28003e6SMatthew G. Knepley $ limit  - The maximum cell volume for a cell containing this point
2565b28003e6SMatthew G. Knepley 
2566b28003e6SMatthew G. Knepley   Level: developer
2567b28003e6SMatthew G. Knepley 
2568b28003e6SMatthew G. Knepley .seealso: DMRefine(), DMPlexGetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
2569b28003e6SMatthew G. Knepley @*/
2570b28003e6SMatthew G. Knepley PetscErrorCode DMPlexSetRefinementFunction(DM dm, PetscErrorCode (*refinementFunc)(const PetscReal [], PetscReal *))
2571b28003e6SMatthew G. Knepley {
2572b28003e6SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
2573b28003e6SMatthew G. Knepley 
2574b28003e6SMatthew G. Knepley   PetscFunctionBegin;
2575b28003e6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2576b28003e6SMatthew G. Knepley   mesh->refinementFunc = refinementFunc;
2577b28003e6SMatthew G. Knepley   PetscFunctionReturn(0);
2578b28003e6SMatthew G. Knepley }
2579b28003e6SMatthew G. Knepley 
2580b28003e6SMatthew G. Knepley /*@
2581b28003e6SMatthew G. Knepley   DMPlexGetRefinementFunction - Get the function giving the maximum cell volume for refinement
2582b28003e6SMatthew G. Knepley 
2583b28003e6SMatthew G. Knepley   Input Parameter:
2584b28003e6SMatthew G. Knepley . dm - The DM
2585b28003e6SMatthew G. Knepley 
2586b28003e6SMatthew G. Knepley   Output Parameter:
2587b28003e6SMatthew G. Knepley . refinementFunc - Function giving the maximum cell volume in the refined mesh
2588b28003e6SMatthew G. Knepley 
2589b28003e6SMatthew G. Knepley   Note: The calling sequence is refinementFunc(coords, limit)
2590b28003e6SMatthew G. Knepley $ coords - Coordinates of the current point, usually a cell centroid
2591b28003e6SMatthew G. Knepley $ limit  - The maximum cell volume for a cell containing this point
2592b28003e6SMatthew G. Knepley 
2593b28003e6SMatthew G. Knepley   Level: developer
2594b28003e6SMatthew G. Knepley 
2595b28003e6SMatthew G. Knepley .seealso: DMRefine(), DMPlexSetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
2596b28003e6SMatthew G. Knepley @*/
2597b28003e6SMatthew G. Knepley PetscErrorCode DMPlexGetRefinementFunction(DM dm, PetscErrorCode (**refinementFunc)(const PetscReal [], PetscReal *))
2598b28003e6SMatthew G. Knepley {
2599b28003e6SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
2600b28003e6SMatthew G. Knepley 
2601b28003e6SMatthew G. Knepley   PetscFunctionBegin;
2602b28003e6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2603b28003e6SMatthew G. Knepley   PetscValidPointer(refinementFunc,  2);
2604b28003e6SMatthew G. Knepley   *refinementFunc = mesh->refinementFunc;
2605b28003e6SMatthew G. Knepley   PetscFunctionReturn(0);
2606b28003e6SMatthew G. Knepley }
2607b28003e6SMatthew G. Knepley 
26080d1cd5e0SMatthew G. Knepley PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined)
26090d1cd5e0SMatthew G. Knepley {
2610492b8470SStefano Zampini   PetscBool         isUniform;
2611*412e9a14SMatthew G. Knepley   DMPlexCellRefiner cr;
26120d1cd5e0SMatthew G. Knepley   PetscErrorCode    ierr;
26130d1cd5e0SMatthew G. Knepley 
26140d1cd5e0SMatthew G. Knepley   PetscFunctionBegin;
26150d1cd5e0SMatthew G. Knepley   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
2616*412e9a14SMatthew G. Knepley   ierr = DMViewFromOptions(dm, NULL, "-initref_dm_view");CHKERRQ(ierr);
26170d1cd5e0SMatthew G. Knepley   if (isUniform) {
2618492b8470SStefano Zampini     PetscBool localized;
26190d1cd5e0SMatthew G. Knepley 
2620*412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerCreate(dm, &cr);CHKERRQ(ierr);
2621*412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
2622492b8470SStefano Zampini     ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
2623*412e9a14SMatthew G. Knepley     ierr = DMPlexRefineUniform(dm, cr, dmRefined);CHKERRQ(ierr);
26249a7e3c0aSMatthew G. Knepley     ierr = DMPlexSetRegularRefinement(*dmRefined, PETSC_TRUE);CHKERRQ(ierr);
26250d1cd5e0SMatthew G. Knepley     ierr = DMCopyBoundary(dm, *dmRefined);CHKERRQ(ierr);
26260d1cd5e0SMatthew G. Knepley     if (localized) {ierr = DMLocalizeCoordinates(*dmRefined);CHKERRQ(ierr);}
2627*412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
26280d1cd5e0SMatthew G. Knepley   } else {
26290d1cd5e0SMatthew G. Knepley     ierr = DMPlexRefine_Internal(dm, NULL, dmRefined);CHKERRQ(ierr);
26300d1cd5e0SMatthew G. Knepley   }
26310d1cd5e0SMatthew G. Knepley   PetscFunctionReturn(0);
26320d1cd5e0SMatthew G. Knepley }
26330d1cd5e0SMatthew G. Knepley 
26340d1cd5e0SMatthew G. Knepley PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM dmRefined[])
26350d1cd5e0SMatthew G. Knepley {
26360d1cd5e0SMatthew G. Knepley   DM             cdm = dm;
26370d1cd5e0SMatthew G. Knepley   PetscInt       r;
26380d1cd5e0SMatthew G. Knepley   PetscBool      isUniform, localized;
26390d1cd5e0SMatthew G. Knepley   PetscErrorCode ierr;
26400d1cd5e0SMatthew G. Knepley 
26410d1cd5e0SMatthew G. Knepley   PetscFunctionBegin;
26420d1cd5e0SMatthew G. Knepley   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
26430d1cd5e0SMatthew G. Knepley   ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
26440d1cd5e0SMatthew G. Knepley   if (isUniform) {
26450d1cd5e0SMatthew G. Knepley     for (r = 0; r < nlevels; ++r) {
2646*412e9a14SMatthew G. Knepley       DMPlexCellRefiner cr;
26470d1cd5e0SMatthew G. Knepley 
2648*412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerCreate(cdm, &cr);CHKERRQ(ierr);
2649*412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
2650*412e9a14SMatthew G. Knepley       ierr = DMPlexRefineUniform(cdm, cr, &dmRefined[r]);CHKERRQ(ierr);
26519a7e3c0aSMatthew G. Knepley       ierr = DMSetCoarsenLevel(dmRefined[r], cdm->leveldown);CHKERRQ(ierr);
26529a7e3c0aSMatthew G. Knepley       ierr = DMSetRefineLevel(dmRefined[r], cdm->levelup+1);CHKERRQ(ierr);
26530d1cd5e0SMatthew G. Knepley       ierr = DMCopyBoundary(cdm, dmRefined[r]);CHKERRQ(ierr);
26540d1cd5e0SMatthew G. Knepley       if (localized) {ierr = DMLocalizeCoordinates(dmRefined[r]);CHKERRQ(ierr);}
26550d1cd5e0SMatthew G. Knepley       ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr);
26560d1cd5e0SMatthew G. Knepley       ierr = DMPlexSetRegularRefinement(dmRefined[r], PETSC_TRUE);CHKERRQ(ierr);
26570d1cd5e0SMatthew G. Knepley       cdm  = dmRefined[r];
2658*412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
26590d1cd5e0SMatthew G. Knepley     }
26600d1cd5e0SMatthew G. Knepley   } else {
26610d1cd5e0SMatthew G. Knepley     for (r = 0; r < nlevels; ++r) {
26620d1cd5e0SMatthew G. Knepley       ierr = DMRefine(cdm, PetscObjectComm((PetscObject) dm), &dmRefined[r]);CHKERRQ(ierr);
26630d1cd5e0SMatthew G. Knepley       ierr = DMCopyBoundary(cdm, dmRefined[r]);CHKERRQ(ierr);
26640d1cd5e0SMatthew G. Knepley       if (localized) {ierr = DMLocalizeCoordinates(dmRefined[r]);CHKERRQ(ierr);}
26650d1cd5e0SMatthew G. Knepley       ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr);
26660d1cd5e0SMatthew G. Knepley       cdm  = dmRefined[r];
26670d1cd5e0SMatthew G. Knepley     }
26680d1cd5e0SMatthew G. Knepley   }
26690d1cd5e0SMatthew G. Knepley   PetscFunctionReturn(0);
26700d1cd5e0SMatthew G. Knepley }
2671